Git Product home page Git Product logo

m2-isa-r's People

Contributors

fpedd avatar wysiwyng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

m2-isa-r's Issues

Overflow dropping in summation operation

I realized in the below operation wrong return value Z is generated during the summation of X and Y:

unsigned<64> foo(unsigned<32> X, unsigned<32> Y){
    unsigned<64> Z = X + Y;
    return Z;
}

I believe this is due to the fact that X and Y are translating to C types (etiss_uint32) and their summation also returns etiss_uint32 which drops the overflow value(32nd bit).

However when I do casting explicitly as follows:

unsigned<64> foo(unsigned<32> X, unsigned<32> Y){
    unsigned<64> Z = (unsigned<64>)X + (unsigned<64>)Y;
    return Z;
}

It works pretty well.

But coredsl2 manual guarantees no dropping is occurring by simply setting the width of the result value to wr = max(w1 + 1, w2 + 1). Should not M2-ISA-R also guarantee this? This is leading to a lot of unexpected behaviors.

Thanks a lot!

Index to Register File for Compressed Instructions not correctly handled

If the index to the register file for data writeback is not static (i.e. not constant or not part of the instruction encoding), M2-ISA-R has issues getting the scope right. I guess this is a rare edge case, as it is generally not allowed to index the register file using "runtime data" (normally the source and destination register indexes are part of the instruction itself, correct me if I am wrong here). However, the CIW, CL, CS, and CB encodings of the compressed instruction set allow only a subset of the 32 register file to be accessed. Therefore, they only allow access to 8 registers (hence the 3 bit wide rs1 field below). This is elegantly implemented in the CoreDSL by adding 8 to the 3bit rs1 index, thus allowing access to registers x8-x15.

For example, let us have a look at the compressed shift right logical immediate instruction:

C.SRLI {//(RV32 nse)
    encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01;
    args_disass: "{name(8+rs1)}, {shamt}";
    val rs1_idx[5] <= rs1+8;
    X[rs1_idx] <= shrl(X[rs1_idx], shamt);
}

which generates the following behaviour code:

...
1:etiss_uint32 shamt = 0;
2: static BitArrayRange R_shamt_0(6, 2);
3: shamt += R_shamt_0.read(ba) << 0;
4: etiss_uint32 rs1 = 0;
5: static BitArrayRange R_rs1_0(9, 7);
6: rs1 += R_rs1_0.read(ba) << 0;
7: 
8: // -----------------------------------------------------------------------------
9: 
10:		CodePart & partInit = cs.append(CodePart::INITIALREQUIRED);
11:
12:		partInit.code() = std::string("//C.SRLI\n");
13:
14: // -----------------------------------------------------------------------------
15: partInit.code() += "etiss_uint8 rs1_idx = (" + std::to_string(rs1 + 8) + ") & 0x1f;\n";
16: partInit.code() += "*((RISCV*)cpu)->X[rs1_idx] = (*((RISCV*)cpu)->X[rs1_idx]) >> (" + std::to_string(shamt) + ");\n";
17: partInit.code() += "cpu->instructionPointer = " + std::to_string(ic.current_address_ + 2) + ";\n";
18: // -----------------------------------------------------------------------------
19:
20:		partInit.getRegisterDependencies().add(reg_name[rs1_idx], 32);
21:		partInit.getAffectedRegisters().add(reg_name[rs1_idx], 32);
22:		partInit.getAffectedRegisters().add("instructionPointer", 32);
...

While the "static" variables in lines 1-6 work just fine, the addition in the behaviour part of the instruction in line 15 causes the rs1_idx variable to be in the scope of the jit code. This raises an error in lines 20-21 when rs1_idx is referenced outside the jit code.

Now a simple fix would be to get rid of the rs1_idx variable, like so:

C.SRLI {//(RV32 nse)
    encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01;
    args_disass: "{name(8+rs1)}, {shamt}";
    X[ rs1+8] <= shrl(X[ rs1+8], shamt);
}

However, this would make M2-ISA-R not compatible with the RISC-V CoreDSLs provided by Minres.

Another approach would be to detect if an assignment is completely "static" and then put its "target" variable outside the jit code (this would help ETISS runtime performance as well).

Or one could inline such simple expressions at compile-time, producing my "hand-optimized" code from above,. However, this is probably the most labour intensive approach concerning the required changes to M2-ISA-R.

PC access in functions does not yield correct results

void pctest(int a, int b) {
  X[a] = PC;
  PC = X[b];
}

is translated to:

static inline void pctest(ETISS_CPU * const cpu, ETISS_System * const system, void * const * const plugin_pointers, etiss_int32 a, etiss_int32 b)
{
  ((test_core*)cpu)->X[a] = ic.current_address_;
  cpu->instructionPointer = ((test_core*)cpu)->X[b];
}

where ic.current_address_ can not be accessed in function context.

GDB Register Print Support in `RISCVVGDBCore.h`

As of now, M2-ISA-R does not generate any code for register printing via GDB in RISCVVGDBCore.h. It only provides a comment Further register should be added here to send data over gdbserver. Is that intended?

The ArchImpl in ETISS has the mapRegister method already implemented.

slicing is not working correctly for extern variables

Hello

I just realized the following code:

architectural_state { 
  extern unsigned<8> ITSTATE;
}
bool it_passed(){
  unsigned<4> cond = 0;
  
  if(ITSTATE[3:0] != 0)
    cond = ITSTATE[7:4];
  else if(ITSTATE==0)
    cond = 14;
  bool result = condition_passed(cond);
  
  ///// advance IT
  if (ITSTATE[2:0]== 0) ITSTATE=0;
  else states = ITSTATE[7:5] :: (unsigned<6>) LSL(ITSTATE[4:0], 1);

  return result;
}

is producing the following code:

// in ARMv7M.h file
etiss_uint8 ITSTATE; 
static inline etiss_uint8 it_passed (ETISS_CPU * const cpu, ETISS_System* const system, void* const* const plugin_pointers)
{
  etiss_uint8 cond = (0U) & 0xf;
  
  if (((ARMv7M*)cpu)->ITSTATE[3U] & 1U)
    cond = (((ARMv7M*)cpu)->ITSTATE[7U]) & 0xf;
  else 
    if (((ARMv7M*)cpu)->ITSTATE == 0U) 
      cond = (14U) & 0xf;

  etiss_uint8 result = (condition_passed(cpu, system, plugin_pointers, cond)) & 0x1;

  if (((ARMv7M*)cpu)->ITSTATE[2U] == 0U)
    ((ARMv7M*)cpu)->ITSTATE = 0U;
  else
    ((ARMv7M*)cpu)->ITSTATE = (((((ARMv7M*)cpu)->ITSTATE[7U])<< 6) | ((etiss_uint8)((LSL(((ARMv7M*)cpu)->ITSTATE[4U], 1U) & 0x3f))));

  return result;}

where you might have already seen the resulting indexes of ITSTATE after slicing are completely wrong.

However when I create a local copy of the extern variable ITSTATE as follows:

architectural_state { 
  extern unsigned<8> ITSTATE;
}

bool it_passed(){
  unsigned<4> cond = 0;
  unsigned<8> states = ITSTATE;      /// local copy of the same type
  
  if(states[3:0] & 0xf  != 0)
    cond = states[7:4];
  else if(states == 0)
    cond = 14;

  bool result = condition_passed(cond);
  ///// advance IT
  if (states[2:0] == 0) states = 0;
  else states = states[7:5] :: (unsigned<6>)LSL(states[4:0], 1);
  
  ITSTATE = states; // put the result back
  return result;
}

The following true expected code is generated.

static inline etiss_uint8 it_passed (ETISS_CPU * const cpu, ETISS_System* const system, void *const * const plugin_pointers){
  etiss_uint8 cond = (0U) & 0xf;
  etiss_uint8 states = ((ARMv7M*)cpu)->ITSTATE; 
  if ((((states) >> (0U)) & 15) & 1U)
    cond = ((((states) >> (4U)) & 15)) & 0xf;
  else
    if (states == 0U)
      cond = (14U) & 0xf;
  
  etiss_uint8 result = (condition_passed(cpu, system, plugin_pointers, cond)) & 0x1;
  
  if ((((states) >> (0U)) & 7) == 0U)
    states = 0U;
  else 
    states = ((((((states) >> (5U)) & 7)) << 6) | ((etiss_uint8)((LSL((((states)>> (0U)) & 31), 1U) & 0x3f))));
  
  ((ARMv7M*)cpu)->ITSTATE = states;
  
  return result;}

But why this is happening in the first place even though states and ITSTATE are of the same type of etiss_uint8? Is there something wrong with extern variables?

Thanks

Type casting

Signed registers declared in the CoreDSL2 model are converted to unsigned in ETISS.

Nested static statements

M2-ISA-R currently produces "nested" static statements by calling make_static() on statements that were already made static. This leads to code like this:

partInit.code() += "_illmask = " + std::to_string((1) << (" + std::to_string(32 - 1) + ")) + ";\n";

See 16e0bcb for an extremely dirty fix.

Wrong code is generated in concatenation operation

I was following the coredsl2 manual and I am having trouble using the concatenation operator during etiss code generation phase.

As an example the following behavioral model:
image

is generating the following code:
generated

where imm is shifted 3 times although it should have been shifted by 2.

As another example:
image

is generating the following code:
image

where im11 has not been shifted at all.

I am not sure if I am missing something or this is a possible bug. Do you have any idea?

Sliced width is ignored during concatenation

Hello,

the following coredsl2 code:

void foo(){
  unsigned<8> a = 3;
  unsigned<8> b = 1;
  unsigned<32> x = 0, y=0;
  unsigned<64> z = x::y[a:b];
}

is producing:

static inline void foo (){
  etiss_uint8 a = 3U;
  etiss_uint8 b = 1U;
  etiss_uint32 x = 0U;
  etiss_uint32 y = 0U;
  etiss_uint64 z = (((x) << 32) | ((((y) >> (b)) & ((1 << ((a) - (b) + 1)) - 1))));
}

where x has been shifted 32 times instead of a - b + 1 times.

However, putting numbers into slices:

void foo(){
  unsigned<32> x = 0, y=0;
  unsigned<64> z = x::y[3:1];
}

works quite well:

static inline void foo (){
  etiss_uint32 x = 0U;
  etiss_uint32 y = 0U;
  etiss_uint64 z = (((x) << 3) | ((((y) >> (1U)) & 7)));
}

any idea about this?

Left-hand indexing not supported

The following code does not work with the CoreDSL2 frontend and the ETISS backend:

VXSAT_CSS[0] = 0b1;

As a workaround VXSAT_CSR = VXSAT_CSR | 0b1; works just fine.

Memory read inside if-statement not generating correct code

Hello,
I have noticed that a memory access placed inside of an if statement does not generate code for actually reading the memory.

A small example:
This behavior describtion generates the following code:

behavior: {
    if ((signed<32>)MEM[0] > 0)
        X[1] = 1;
}
partInit.code() += "cpu->instructionPointer = " + std::to_string(ic.current_address_ + 4U) + ";\n";
partInit.code() += "if ((etiss_int32)(mem_val_0) > 0U) {\n";
partInit.code() += "*((RV32IMACFD*)cpu)->X[" + std::to_string(1U) + "] = 1U;\n";
partInit.code() += "}\n";

Where I would have expected it to generate the code below or throw an error.

partInit.code() += "cpu->instructionPointer = " + std::to_string(ic.current_address_ + 4U) + ";\n";
partInit.code() += "etiss_uint32 mem_val_0;\n";
partInit.code() += "exception |= (*(system->dread))(system->handle, cpu, " 
                                     + std::to_string(0U) + ", (etiss_uint8*)&mem_val_0, 4);\n";
partInit.code() += "if ((etiss_int32)(mem_val_0) > 0U) {\n";
partInit.code() += "*((RV32IMACFD*)cpu)->X[" + std::to_string(1U) + "] = 1U;\n";
partInit.code() += "}\n";

Thanks

Include some examples / automated testing with github actions

I think it would be helpful to include an example folder that would contain some basic RISCV core modelled in CoreDSL. This could be used to quickly get going and test whether M2-ISA-R is working. One could also use it to run some automated tests using unittest and GitHub actions (including a status badge and what not... :)). Let me know if you think this is useful and I will create a PR.

In the long run, it could be beneficial to have a separate CoreDSL Model repository here on GitHub, similar to the one you have on GitLab @wysiwyng. This Model repository could then be included as a submodule. As this tool is the only way one can actually use the CoreDSL Models for anything meaningful, I would find this "relative tight coupling" between models and generator not too problematic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.