FPGA-Research-Manchester / FABulous

Fabric generator and CAD tools
https://fabulous.readthedocs.io/en/latest/
Apache License 2.0
147 stars 33 forks source link

"enum" parameter bitstream mapping #52

Open gatecat opened 2 years ago

gatecat commented 2 years ago

consider this somewhat pointless example of a primitive the end user might instantiate

module LOGIC_GATE(input A, B, output X);
parameter MODE = "AND";
generate
   if (MODE == "AND") assign X = A & B;
   else if (MODE == "OR") assign X = A | B;
   else if (MODE == "XOR") assign X = A ^ B;
endgenerate
endmodule

this would generate a FASM configuration feature in nextpnr like X6Y9A.MODE.AND or X6Y9A.MODE.XOR

the underlying hardware primitive might look like

module LOGIC_GATE(input A, B, input [1:0] ConfigBits, output X);
parameter MODE = "AND";

assign X = (ConfigBits == 2'b01) ? (A & B) :
   (ConfigBits == 2'b10) ? (A | B) :
  (ConfigBits == 2'b11) ? (A ^ B) :
  1'bx;

endmodule

we now need some way of specifying the mapping of

MODE.AND => ConfigBits[1:0]=2'b01
MODE.OR => ConfigBits[1:0]=2'b10
MODE.XOR => ConfigBits[1:0]=2'b11

the encoding being just an example, others might be possible

one way of doing this using attributes might be like

(* FABulous, BelMap,
MODE_start=0,
MODE_end=1,
MODE_enum,
MODE_AND=2'b01,
MODE_OR=2'b10,
MODE_XOR=2'b11,
*)

essentially, we need to specify more things for MODE than just a single bit mapping - the range of bits it maps to and the set of possible values. Same for multi-bit non-enumarated configuration values (like the initial accumulator value of a DSP), which in this syntax could perhaps just specify _start and _end attributes without any of the enum stuff.

KelvinChung2000 commented 2 years ago

I am thinking maybe something like this:

(* FABulous, BelEnum, MODE.
ADD,
OR,
XOR
*)
(* Fabulous, BelMap,
start=0,
end=1,
some_init_value=Vector(2)
MODE
*)

Then the AND, OR, XOR will get automatically assigned to b00, b01, b10. This might make parsing multiple enums easier. The Vector(2) will be indicated using 2 bits for the some_init_value

gatecat commented 2 years ago

Then the AND, OR, XOR will get automatically assigned to b00, b01, b10

We want to have the ability to support custom encodings though.

Actually, Dirk did suggest out-of-band going back to hot comments here, if that's easier to work with. Something like

// bitstream encoding
// parameter MODE [1:0]
// AND=2'b01
// ..
// end MODE

this would specify that MODE is located in bits 1..0 and the encoding of AND etc but we could maybe have something like this as attributes still too?

KelvinChung2000 commented 2 years ago

I don't think going back to comment will be a good idea. This should just do the same,

(* FABulous, BelEnum, MODE[1:0],
ADD=01,
OR=10,
XOR=11
*)
gatecat commented 2 years ago

Looks good!

KelvinChung2000 commented 2 years ago

Now the following Bel map:

(* FABulous, BelEnum, MODE1[1:0],
A=001,
B=010,
C=011,
*)
(* FABulous, BelEnum, MODE2[0:1],
ADD=01,
OR=10,
XOR=11
*)
(* Fabulous, BelMap,
test=0,
MODE2,
some_init_value1=1:0,
some_init_value2=0:1,
MODE1
*)

will yield the following dictionary after parsing.

{
   "test":{
      "0":{
         "0":"1"
      }
   },
   "MODE2":{
      "ADD":{
         "0":"0",
         "1":"1"
      },
      "OR":{
         "0":"1",
         "1":"0"
      },
      "XOR":{
         "0":"1",
         "1":"1"
      }
   },
   "some_init_value1":{
      "3":{
         "1":"1",
         "0":"1"
      },
      "2":{
         "1":"1",
         "0":"0"
      },
      "1":{
         "1":"0",
         "0":"1"
      },
      "0":{
         "1":"0",
         "0":"0"
      }
   },
   "some_init_value2":{
      "0":{
         "1":"1",
         "0":"1"
      },
      "1":{
         "1":"1",
         "0":"0"
      },
      "2":{
         "1":"0",
         "0":"1"
      },
      "3":{
         "1":"0",
         "0":"0"
      }
   },
   "MODE1":{
      "A":{
         "1":"0",
         "0":"0"
      },
      "B":{
         "1":"0",
         "0":"1"
      },
      "C":{
         "1":"0",
         "0":"1"
      }
   }
}

I have further looked into bitstream generation to support with an enum, but it looks like that will also require refactoring.

gatecat commented 2 years ago

looks good!