[03/23] sim/erc32: Perform pseudo-init of system if binary starts from non-zero address.

Message ID 1424159099-5148-4-git-send-email-jiri@gaisler.se
State Superseded
Headers

Commit Message

Jiri Gaisler Feb. 17, 2015, 7:44 a.m. UTC
  Binaries produced by most erc32 tool-chains do not include
system initialization. sis will detect this and initialize
necessary registers for memory and timer control.

	* erc32.c (mec_read) allow simulator memory size to be read
	by application. (boot_init) initialize memory and timers if
	start address is not 0.

	* erc32,c (exe_cmd) call boot_init if start address not 0
	* interf.c (run_sim) Likewise
---
 sim/erc32/erc32.c  | 24 ++++++++++++++++++++++++
 sim/erc32/func.c   |  1 +
 sim/erc32/interf.c |  1 +
 3 files changed, 26 insertions(+)
  

Comments

Mike Frysinger Feb. 17, 2015, 8:59 a.m. UTC | #1
On 17 Feb 2015 08:44, Jiri Gaisler wrote:
> +extern struct pstate sregs;
> +
> +void
> +boot_init ()

in C, you need to do (void) to avoid ugliness.

also looks like this is missing an update to a header to add the prototype ?

> +{
> +    mec_write(MEC_WCR, 0);	/* zero waitstates */
> +    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
> +    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
> +    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
> +    sregs.wim = 2;
> +    sregs.psr = 0x110010e0;
> +    sregs.r[30] = RAM_END;
> +    sregs.r[14] = sregs.r[30] - 96*4;
> +    mec_mcr |= 1;		/* power-down enabled */
> +}

why isn't sregs passed in as an arg ?  looks like both callers have a pointer to 
it already.

> --- a/sim/erc32/func.c
> +++ b/sim/erc32/func.c
> @@ -468,6 +468,7 @@ exec_cmd(sregs, cmd)
>  	    }
>  	    sregs->pc = len & ~3;
>  	    sregs->npc = sregs->pc + 4;
> +	    if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();

i know the code base doesn't follow GNU style already, but lets at least start 
moving in that direction.  i.e. uncuddle this:
	if (...)
	  boot_init();

> --- a/sim/erc32/interf.c
> +++ b/sim/erc32/interf.c
> @@ -78,6 +78,7 @@ run_sim(sregs, icount, dis)
>     init_stdio();
>     sregs->starttime = time(NULL);
>     irq = 0;
> +   if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();

same here
-mike
  
Jiri Gaisler Feb. 18, 2015, 2:40 p.m. UTC | #2
On 02/17/2015 09:59 AM, Mike Frysinger wrote:
> On 17 Feb 2015 08:44, Jiri Gaisler wrote:
>> +extern struct pstate sregs;
>> +
>> +void
>> +boot_init ()
> 
> in C, you need to do (void) to avoid ugliness.

Will fix.

> 
> also looks like this is missing an update to a header to add the prototype ?

This is done in patch (17/23).

> 
>> +{
>> +    mec_write(MEC_WCR, 0);	/* zero waitstates */
>> +    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
>> +    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
>> +    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
>> +    sregs.wim = 2;
>> +    sregs.psr = 0x110010e0;
>> +    sregs.r[30] = RAM_END;
>> +    sregs.r[14] = sregs.r[30] - 96*4;
>> +    mec_mcr |= 1;		/* power-down enabled */
>> +}
> 
> why isn't sregs passed in as an arg ?  looks like both callers have a pointer to 
> it already.

I am saving this for next major update - SMP support. All globals will then
be removed and the full cpu state will be in a struct that is passed to the
simulation engine. In this way I can simulate multiple cpu's.

Jiri.
  
Mike Frysinger Feb. 18, 2015, 4:53 p.m. UTC | #3
On 18 Feb 2015 15:40, Jiri Gaisler wrote:
> On 02/17/2015 09:59 AM, Mike Frysinger wrote:
> > On 17 Feb 2015 08:44, Jiri Gaisler wrote:
> >> +extern struct pstate sregs;
> >> +
> >> +void
> >> +boot_init ()
> > 
> > also looks like this is missing an update to a header to add the prototype ?
> 
> This is done in patch (17/23).

ok, but patches things really should be standalone.  although your series is
pretty good already in terms of splitting things apart.

> >> +{
> >> +    mec_write(MEC_WCR, 0);	/* zero waitstates */
> >> +    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
> >> +    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
> >> +    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
> >> +    sregs.wim = 2;
> >> +    sregs.psr = 0x110010e0;
> >> +    sregs.r[30] = RAM_END;
> >> +    sregs.r[14] = sregs.r[30] - 96*4;
> >> +    mec_mcr |= 1;		/* power-down enabled */
> >> +}
> > 
> > why isn't sregs passed in as an arg ?  looks like both callers have a pointer to 
> > it already.
> 
> I am saving this for next major update - SMP support. All globals will then
> be removed and the full cpu state will be in a struct that is passed to the
> simulation engine. In this way I can simulate multiple cpu's.

can't this particular bit be done already ?  or is the global pointer diff from
the local one ?
-mike
  
Jiri Gaisler Feb. 19, 2015, 4:11 p.m. UTC | #4
On 02/18/2015 05:53 PM, Mike Frysinger wrote:
> On 18 Feb 2015 15:40, Jiri Gaisler wrote:
>> On 02/17/2015 09:59 AM, Mike Frysinger wrote:
>>> On 17 Feb 2015 08:44, Jiri Gaisler wrote:
>>>> +extern struct pstate sregs;
>>>> +
>>>> +void
>>>> +boot_init ()
>>>
>>> also looks like this is missing an update to a header to add the prototype ?
>>
>> This is done in patch (17/23).
> 
> ok, but patches things really should be standalone.  although your series is
> pretty good already in terms of splitting things apart.
> 
>>>> +{
>>>> +    mec_write(MEC_WCR, 0);	/* zero waitstates */
>>>> +    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
>>>> +    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
>>>> +    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
>>>> +    sregs.wim = 2;
>>>> +    sregs.psr = 0x110010e0;
>>>> +    sregs.r[30] = RAM_END;
>>>> +    sregs.r[14] = sregs.r[30] - 96*4;
>>>> +    mec_mcr |= 1;		/* power-down enabled */
>>>> +}
>>>
>>> why isn't sregs passed in as an arg ?  looks like both callers have a pointer to 
>>> it already.
>>
>> I am saving this for next major update - SMP support. All globals will then
>> be removed and the full cpu state will be in a struct that is passed to the
>> simulation engine. In this way I can simulate multiple cpu's.
> 
> can't this particular bit be done already ?  or is the global pointer diff from
> the local one ?

The global pointer is not different from the local, but since the global is
used in so many places it does not seem logical to switch to a local copy just
here. That is why I would like to keep this as is and remove all globals in
a later patch.

Jiri.

> -mike
>
  
Mike Frysinger Feb. 19, 2015, 5:47 p.m. UTC | #5
On 19 Feb 2015 17:11, Jiri Gaisler wrote:
> On 02/18/2015 05:53 PM, Mike Frysinger wrote:
> > On 18 Feb 2015 15:40, Jiri Gaisler wrote:
> >> On 02/17/2015 09:59 AM, Mike Frysinger wrote:
> >>> On 17 Feb 2015 08:44, Jiri Gaisler wrote:
> >>>> +{
> >>>> +    mec_write(MEC_WCR, 0);	/* zero waitstates */
> >>>> +    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
> >>>> +    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
> >>>> +    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
> >>>> +    sregs.wim = 2;
> >>>> +    sregs.psr = 0x110010e0;
> >>>> +    sregs.r[30] = RAM_END;
> >>>> +    sregs.r[14] = sregs.r[30] - 96*4;
> >>>> +    mec_mcr |= 1;		/* power-down enabled */
> >>>> +}
> >>>
> >>> why isn't sregs passed in as an arg ?  looks like both callers have a pointer to 
> >>> it already.
> >>
> >> I am saving this for next major update - SMP support. All globals will then
> >> be removed and the full cpu state will be in a struct that is passed to the
> >> simulation engine. In this way I can simulate multiple cpu's.
> > 
> > can't this particular bit be done already ?  or is the global pointer diff from
> > the local one ?
> 
> The global pointer is not different from the local, but since the global is
> used in so many places it does not seem logical to switch to a local copy just
> here. That is why I would like to keep this as is and remove all globals in
> a later patch.

there's already funcs that accept it as a pointer and operate on it in this 
code base.  since you're creating this function for the first time, it seems 
natural to include the right change from the start to reduce code shuffling 
later on.

if you're really set on this route though, i won't belabor the point (even if i 
think i'm right ;]).
-mike
  

Patch

diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c
index 4d4177e..4fa8f61 100644
--- a/sim/erc32/erc32.c
+++ b/sim/erc32/erc32.c
@@ -743,6 +743,14 @@  mec_read(addr, asi, data)
 	*data = read_uart(addr);
 	break;
 
+    case 0xF4:		/* simulator RAM size in bytes */
+	*data = 4096*1024;
+	break;
+
+    case 0xF8:		/* simulator ROM size in bytes */
+	*data = 1024*1024;
+	break;
+
     default:
 	set_sfsr(MEC_ACC, addr, asi, 1);
 	return (1);
@@ -1887,3 +1895,19 @@  sis_memory_read(addr, data, length)
     memcpy(data, mem, length);
     return (length);
 }
+
+extern struct pstate sregs;
+
+void
+boot_init ()
+{
+    mec_write(MEC_WCR, 0);	/* zero waitstates */
+    mec_write(MEC_TRAPD, 0);	/* turn off watch-dog */
+    mec_write(MEC_RTC_SCALER, sregs.freq-1); /* generate 1 MHz RTC tick */
+    mec_write(MEC_MEMCFG, (3 << 18) | (4 << 10)); /* 1 MB ROM, 4 MB RAM */
+    sregs.wim = 2;
+    sregs.psr = 0x110010e0;
+    sregs.r[30] = RAM_END;
+    sregs.r[14] = sregs.r[30] - 96*4;
+    mec_mcr |= 1;		/* power-down enabled */
+}
diff --git a/sim/erc32/func.c b/sim/erc32/func.c
index e6744ee..7034393 100644
--- a/sim/erc32/func.c
+++ b/sim/erc32/func.c
@@ -468,6 +468,7 @@  exec_cmd(sregs, cmd)
 	    }
 	    sregs->pc = len & ~3;
 	    sregs->npc = sregs->pc + 4;
+	    if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
 	    printf("resuming at 0x%08x\n",sregs->pc);
 	    if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) {
 		stat = run_sim(sregs, VAL(cmd2), 0);
diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c
index 63b3f38..9ac455f 100644
--- a/sim/erc32/interf.c
+++ b/sim/erc32/interf.c
@@ -78,6 +78,7 @@  run_sim(sregs, icount, dis)
    init_stdio();
    sregs->starttime = time(NULL);
    irq = 0;
+   if ((sregs->pc != 0) && (ebase.simtime == 0)) boot_init();
    while (!sregs->err_mode & (icount > 0)) {
 
 	sregs->fhold = 0;