All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bitstream.compiler.Handlers.scala Maven / Gradle / Ivy

The newest version!
package bitstream.compiler

trait NodeHandler {
  protected var id: Int
  def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
            (Netlist, String)
}

/*
 * Node Handlers
 * -------------
 * Intended usage:
 * - Compile the Bitstream JAR file along with your source
 * - Add `import bitstream.compiler.NodeHandlers._` to your source
 * - Instantiate a handler with `var addHandler = new AddHandler()`
 * - Use the handler with `addHandler.create(...)` passing in and out the global netlist
 */
object NodeHandlers {

  val stdComment = "// Autogenerated by Bitstream DSL compiler"

  def addFeedback(name: String, init: String, decorr: String, input: String, size: Tuple2[Int, Int], netList: Netlist):
                 (Netlist, String) = {
    // Create copy of netlist
    var newNetList = netList

    // Update netlist
    newNetList.addWire(input, size, true, false)
    newNetList.addWire(name, size, true, false)

    // Create Verilog string
    var outputString = s"""
      |$stdComment
      |// BEGIN feedback${input}
      |assign ${input}_p = switch_inputs ? ${decorr}_p : ${init}_p;
      |assign ${input}_m = switch_inputs ? ${decorr}_m : ${init}_m;
      |// END feedback${input}
      """.stripMargin

    (newNetList, outputString)
  }

  def addModuleInstance(name: String, module: String, params: List[String],
                        inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
      (Netlist, String) = {
    // Create copy of netlist
    var newNetList = netList

    // Add inputs to netlist
    for ((name, size) <- (inputs zip sizes.dropRight(1)).toMap) {
      newNetList.addWire(name, size, false, false)
    }

    // Add output to wire
    newNetList.addWire(output, sizes.last, false, false)

    // Get explicit parameters names
    val builder = (list: List[Tuple2[String, String]], p: String) =>
      list ++ List((p.split("_").last, p))
    val explicitParams = params.foldLeft(List[Tuple2[String, String]]())(builder)

    // Create Verilog string
    var outputString = s"""
      |$stdComment
      |// BEGIN $name
      |$module #(""".stripMargin

    for (param <- explicitParams.dropRight(1)) {
      outputString = outputString + s"""
        |        .${param._1}(${param._2}),""".stripMargin
    }

    outputString = outputString + s"""
      |        .${explicitParams.last._1}(${explicitParams.last._2})
      |    ) $name (""".stripMargin

    outputString = outputString + s"""
      |        CLK, nRST,""".stripMargin

    for (input <- inputs) {
      outputString = outputString + s"""
        |        $input,""".stripMargin
    }

    outputString = outputString + s"""
      |        $output
      |    );
      |// END $name
      """.stripMargin

    (newNetList, outputString)
  }

  def printTopLevel(modName: String, netList: Netlist, bitWidth: String, intWidth: String):
    String = {
    // Add top level name
    var outputString:String = s"module $modName(CLK, nRST, "

    // Add inputs
    outputString =
      netList.inputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, _, _, _) => str + s"${entry._1}_p  " + s"${entry._1}_m  "
                              case Net(false, _, _, _) => str + s"${entry._1}  "
                             }).replaceAll("  ", ", ")

    // Add outputs
    outputString =
      netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                               case Net(true, _, _, _) => str + s"${entry._1}_p  " + s"${entry._1}_m  "
                               case Net(false, _, _, _) => str + s"${entry._1}  "
                              }).trim.replaceAll("  ", ", ")

    outputString = outputString + ");\n\n"

    // Add parameters
    if (bitWidth != "") {
      outputString = outputString + s"parameter BIT_WIDTH = $bitWidth;\n"
      outputString = outputString + s"parameter INT_WIDTH = $intWidth;\n"
    }
    outputString = outputString + "parameter WINDOW_LEN = 100000;\n"
    outputString = outputString + "parameter TICK_COUNTER_SIZE = $clog2(WINDOW_LEN);\n\n"

    // Add CLK and nRST
    outputString = outputString + "input CLK, nRST;\n"

    // Add netlist
    outputString =
      netList.inputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, _, 1, 1) => str + s"input ${entry._1}_p, ${entry._1}_m;\n"
                              case Net(false, _, 1, 1) => str + s"input ${entry._1};\n"
                              case Net(true, _, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"input [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
                              }
                              case Net(false, _, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"input [($widthStr*$depth)-1:0] ${entry._1};\n"
                              }
                             })
    outputString =
      netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, false, 1, 1) => str + s"output ${entry._1}_p, ${entry._1}_m;\n"
                              case Net(false, false, 1, 1) => str + s"output ${entry._1};\n"
                              case Net(true, false, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"output [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
                              }
                              case Net(false, false, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"output [($widthStr*$depth)-1:0] ${entry._1};\n"
                              }
                              case Net(_, _, _, _) => str
                             })
    outputString =
      netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, true, 1, 1) => str + s"output reg ${entry._1}_p, ${entry._1}_m;\n"
                              case Net(false, true, 1, 1) => str + s"output reg ${entry._1};\n"
                              case Net(true, true, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"output reg [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
                              }
                              case Net(false, true, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"output reg [($widthStr*$depth)-1:0] ${entry._1};\n"
                              }
                              case Net(_, _, _, _) => str
                             })
    outputString =
      netList.wires.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, true, 1, 1) => str + s"reg ${entry._1}_p, ${entry._1}_m;\n"
                              case Net(false, true, 1, 1) => str + s"reg ${entry._1};\n"
                              case Net(true, true, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"reg [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
                              }
                              case Net(false, true, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"reg [($widthStr*$depth)-1:0] ${entry._1};\n"
                              }
                              case Net(_, _, _, _) => str
                             })
    outputString =
      netList.wires.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
                              case Net(true, false, 1, 1) => str + s"wire ${entry._1}_p, ${entry._1}_m;\n"
                              case Net(false, false, 1, 1) => str + s"wire ${entry._1};\n"
                              case Net(true, false, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"wire [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
                              }
                              case Net(false, false, width, depth) => {
                                val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
                                str + s"wire [($widthStr*$depth)-1:0] ${entry._1};\n"
                              }
                              case Net(_, _, _, _) => str
                             })

    outputString
  }

  def printUserParams(params: Map[String, String]): String = {
    // Create Verilog string
    var outputString = s"""
      |$stdComment
      |// BEGIN User-defined module parameters
      |""".stripMargin

    for ((param, value) <- params) {
      outputString = outputString + s"parameter $param = $value;\n"
    }

    outputString = outputString + "// END User-defined module parameters\n\n"

    outputString
  }

  def printInputSwitch(): String = {
    var outputString = "\nreg [TICK_COUNTER_SIZE-1:0] tick_counter, next_tick_counter;\n"
    outputString = outputString + "wire switch_inputs;\n\n"
    outputString = outputString +
      s"""|// update tick counter
          |always @(posedge CLK) begin
          |    if (!nRST) begin
          |        tick_counter <= {TICK_COUNTER_SIZE{1'b0}};
          |    end
          |    else begin
          |        tick_counter <= next_tick_counter;
          |    end
          |end
          |// increment the tick counter
          |always @(tick_counter) begin
          |    if (switch_inputs == 1'b0) next_tick_counter <= tick_counter + {{(TICK_COUNTER_SIZE-1){1'b0}}, 1'b1};
          |    else next_tick_counter <= tick_counter;
          |end
          |assign switch_inputs = (tick_counter >= WINDOW_LEN) ? 1'b1 : 1'b0;
      """.stripMargin

    outputString = outputString + "\n\n"

    outputString
  }

  class SAssignHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add output to wire
      newNetList.addWire(output, sizes.head, true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN sassign${id}
        |assign ${output}_p = ${inputs(0)}_p;
        |assign ${output}_m = ${inputs(0)}_m;
        |// END sassign${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DAssignHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, false, false)
      }

      // Add output to wire
      newNetList.addWire(output, sizes.head, false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN dassign${id}
        |assign $output = ${inputs(0)};
        |// END dassign${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SAddHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add internal nets to netlist
      newNetList.addWire(s"add${id}_addPP", sizes.last, false, false)
      newNetList.addWire(s"add${id}_addMM", sizes.last, false, false)

      // Add outputs to netlist
      newNetList.addWire(output, sizes.last, true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN add${id}
        |stoch_add_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) add${id}_PP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_p),
        |        .B(${inputs(1)}_p),
        |        .Y(add${id}_addPP)
        |    );
        |stoch_add_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) add${id}_MM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_m),
        |        .B(${inputs(1)}_m),
        |        .Y(add${id}_addMM)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) add${id}_P (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(add${id}_addPP),
        |        .B(add${id}_addMM),
        |        .Y(${output}_p)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) add${id}_M (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(add${id}_addMM),
        |        .B(add${id}_addPP),
        |        .Y(${output}_m)
        |    );
        |// END add${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SSubHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add internal nets to netlist
      newNetList.addWire(s"sub${id}_addPM", sizes.last, false, false)
      newNetList.addWire(s"sub${id}_addMP", sizes.last, false, false)

      // Add outputs to netlist
      newNetList.addWire(output, sizes.last, true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN sub${id}
        |stoch_add_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) sub${id}_PM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_p),
        |        .B(${inputs(1)}_p),
        |        .Y(sub${id}_addPM)
        |    );
        |stoch_add_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) sub${id}_MP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_m),
        |        .B(${inputs(1)}_m),
        |        .Y(sub${id}_addMP)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) sub${id}_P (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(sub${id}_addPM),
        |        .B(sub${id}_addMP),
        |        .Y(${output}_p)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS(${sizes.last._1}),
        |        .NUM_COLS(${sizes.last._2})
        |    ) sub${id}_M (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(sub${id}_addMP),
        |        .B(sub${id}_addPM),
        |        .Y(${output}_m)
        |    );
        |// END sub${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SMatrixMultiplyHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add internal nets to netlist
      val (m, n) = sizes(0)
      val (_, p) = sizes(1)
      newNetList.addWire(s"mmult${id}_multPP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_multPM", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_multMP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_multMM", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subPPPM", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subPMPP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subMPMM", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subMMMP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subPP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subMP", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subPM", (m, p), false, false)
      newNetList.addWire(s"mmult${id}_subMM", (m, p), false, false)

      // Add outputs to netlist
      newNetList.addWire(output, (m, p), true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN mmult${id}
        |stoch_matrix_mult #(
        |        .NUM_ROWS($m),
        |        .NUM_MID($n),
        |        .NUM_COLS($p)
        |    ) mmult${id}_mPP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_p),
        |        .B(${inputs(1)}_p),
        |        .Y(mmult${id}_multPP)
        |    );
        |stoch_matrix_mult #(
        |        .NUM_ROWS($m),
        |        .NUM_MID($n),
        |        .NUM_COLS($p)
        |    ) mmult${id}_mPM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_p),
        |        .B(${inputs(1)}_m),
        |        .Y(mmult${id}_multPM)
        |    );
        |stoch_matrix_mult #(
        |        .NUM_ROWS($m),
        |        .NUM_MID($n),
        |        .NUM_COLS($p)
        |    ) mmult${id}_mMP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_m),
        |        .B(${inputs(1)}_p),
        |        .Y(mmult${id}_multMP)
        |    );
        |stoch_matrix_mult #(
        |        .NUM_ROWS($m),
        |        .NUM_MID($n),
        |        .NUM_COLS($p)
        |    ) mmult${id}_mMM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(${inputs(0)}_m),
        |        .B(${inputs(1)}_m),
        |        .Y(mmult${id}_multMM)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_PPPM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_multPP),
        |        .B(mmult${id}_multPM),
        |        .Y(mmult${id}_subPPPM)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_PMPP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_multPM),
        |        .B(mmult${id}_multPP),
        |        .Y(mmult${id}_subPMPP)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_MPMM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_multMP),
        |        .B(mmult${id}_multMM),
        |        .Y(mmult${id}_subMPMM)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_MMMP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_multMM),
        |        .B(mmult${id}_multMP),
        |        .Y(mmult${id}_subMMMP)
        |    );
        """.stripMargin
      outputString = outputString + s"""|stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_sPP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subPPPM),
        |        .B(mmult${id}_subMMMP),
        |        .Y(mmult${id}_subPP)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_sMP (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subMPMM),
        |        .B(mmult${id}_subPMPP),
        |        .Y(mmult${id}_subMP)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_sPM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subPMPP),
        |        .B(mmult${id}_subMPMM),
        |        .Y(mmult${id}_subPM)
        |    );
        |stoch_sat_sub_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_sMM (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subMMMP),
        |        .B(mmult${id}_subPPPM),
        |        .Y(mmult${id}_subMM)
        |    );
        |stoch_add_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_P (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subPP),
        |        .B(mmult${id}_subPM),
        |        .Y(${output}_p)
        |    );
        |stoch_add_mat #(
        |        .NUM_ROWS($m),
        |        .NUM_COLS($p)
        |    ) mmult${id}_M (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .A(mmult${id}_subMP),
        |        .B(mmult${id}_subMM),
        |        .Y(${output}_m)
        |    );
        |// END mmult${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SDivHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Determine new names for netlist
      var newNames = inputs :+ output

      // Check sizes
      var newSizes = sizes
      var outputString = ""
      (sizes(0)._1, sizes(0)._2, sizes(1)._1, sizes(1)._2) match {
        case (1, 1, 1, 1) => {
          newSizes = newSizes :+ (1, 1)
          outputString = s"""
            |$stdComment
            |// Start div${id}
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(1),
            |        .NUM_COLS(1)
            |    ) div${id}_P (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_p),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_p)
            |    );
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(1),
            |        .NUM_COLS(1)
            |    ) div${id}_M (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_m),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_m)
            |    );
            |// END div${id}
            """.stripMargin
        }
        case (1, 1, _, _) => {
          newSizes = newSizes :+ sizes.last
          outputString = s"""
            |$stdComment
            |// Start div${id}
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(1)._1}),
            |        .NUM_COLS(${sizes(1)._2})
            |    ) div${id}_P (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A({${sizes(1)._1 * sizes(1)._2}{${inputs(0)}_p}}),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_p)
            |    );
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(1)._1}),
            |        .NUM_COLS(${sizes(1)._2})
            |    ) div${id}_M (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A({${sizes(1)._1 * sizes(1)._2}{${inputs(0)}_m}}),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_m)
            |    );
            |// END div${id}
            """.stripMargin
        }
        case (_, _, 1, 1) => {
          newSizes = newSizes :+ sizes.head
          outputString = s"""
            |$stdComment
            |// Start div${id}
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(0)._1}),
            |        .NUM_COLS(${sizes(0)._2})
            |    ) div${id}_P (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_p),
            |        .B({${sizes(0)._1 * sizes(0)._2}{${inputs(1)}_p}}),
            |        .Y(${output}_p)
            |    );
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(0)._1}),
            |        .NUM_COLS(${sizes(0)._2})
            |    ) div${id}_M (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_m),
            |        .B({${sizes(0)._1 * sizes(0)._2}{${inputs(1)}_p}}),
            |        .Y(${output}_m)
            |    );
            |// END div${id}
            """.stripMargin
        }
        case _ => {
          newSizes = newSizes :+ sizes.last
          outputString = s"""
            |$stdComment
            |// Start div${id}
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(0)._1}),
            |        .NUM_COLS(${sizes(0)._2})
            |    ) div${id}_P (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_p),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_p)
            |    );
            |stoch_div_mat #(
            |        .COUNTER_SIZE(8),
            |        .NUM_ROWS(${sizes(0)._1}),
            |        .NUM_COLS(${sizes(0)._2})
            |    ) div${id}_M (
            |        .CLK(CLK),
            |        .nRST(nRST),
            |        .A(${inputs(0)}_m),
            |        .B(${inputs(1)}_p),
            |        .Y(${output}_m)
            |    );
            |// END div${id}
            """.stripMargin
        }
      }

      // Update netlist
      for ((name, size) <- (newNames zip newSizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      id += 1
      (newNetList, outputString)
    }

  }

  class SFixedGainDivHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      newNetList.addWire(inputs(0), sizes(0), true, false)

      // Add outputs to netlist
      newNetList.addWire(output, sizes.head, true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN fdiv${id}
        |stoch_fixed_gain_div_mat #(
        |        .COUNTER_SIZE(8),
        |        .GAIN(${inputs(1)}),
        |        .NUM_ROWS(${sizes(0)._1}),
        |        .NUM_COLS(${sizes(0)._2})
        |    ) fdiv${id}_P (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .A    (${inputs(0)}_p),
        |        .Y    (${output}_p)
        |    );
        |stoch_fixed_gain_div_mat #(
        |        .COUNTER_SIZE(8),
        |        .GAIN(${inputs(1)}),
        |        .NUM_ROWS(${sizes(0)._1}),
        |        .NUM_COLS(${sizes(0)._2})
        |    ) fdiv${id}_M (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .A    (${inputs(0)}_m),
        |        .Y    (${output}_m)
        |    );
        |// END fdiv${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SL2NormHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (1, 1), true, false)

      val m = if (sizes.head._1 == 1) sizes.head._2 else sizes.head._1

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN l2norm${id}
        |stoch_l2_norm #(
        |        .COUNTER_SIZE(8),
        |        .VEC_LEN($m)
        |    ) l2norm${id} (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .up   (${inputs(0)}_p),
        |        .un   (${inputs(0)}_m),
        |        .y    (${output}_p)
        |    );
        |assign ${output}_m = 1'b0;
        |// END l2norm${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SSqrtHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (1, 1), true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN sqrt${id}
        |stoch_square_root #(
        |        .COUNTER_SIZE(10)
        |    ) sqrt${id} (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .up   (${inputs(0)}_p),
        |        .un   (${inputs(0)}_m),
        |        .y    (${output}_p)
        |    );
        |assign ${output}_m = 1'b0;
        |// END sqrt${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class TransposeHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, sizes.last, true, true)

      // Redeclare integers?
      val intStr = if (id > 0) "" else "integer i, j;"

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN transpose${id}
        |$intStr
        |always @(*) begin
        |    for (i = 0; i < ${sizes.head._1}; i = i + 1) begin
        |        for (j = 0; j < ${sizes.head._2}; j = j + 1) begin
        |            ${output}_p[(j*${sizes.head._1}) + i] <= ${inputs(0)}_p[(i*${sizes.head._2}) + j];
        |            ${output}_m[(j*${sizes.head._1}) + i] <= ${inputs(0)}_m[(i*${sizes.head._2}) + j];
        |        end
        |    end
        |end
        |// END transpose${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class SDecorrelatorHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, true, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, sizes.last, true, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN decorr${id}
        |stoch_decorr_mat #(
        |        .COUNTER_SIZE(8),
        |        .STEP_VAL(16),
        |        .NUM_ROWS(${sizes.head._1}),
        |        .NUM_COLS(${sizes.head._1})
        |    ) decorr${id}_P (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .A    (${inputs(0)}_p),
        |        .Y    (${output}_p)
        |    );
        |stoch_decorr_mat #(
        |        .COUNTER_SIZE(8),
        |        .STEP_VAL(16),
        |        .NUM_ROWS(${sizes.head._1}),
        |        .NUM_COLS(${sizes.head._1})
        |    ) decorr${id}_M (
        |        .CLK  (CLK),
        |        .nRST (nRST),
        |        .A    (${inputs(0)}_m),
        |        .Y    (${output}_m)
        |    );
        |// END decorr${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DAddHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_add${id}
        |determ_add #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) d_add${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_add${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DSubHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_sub${id}
        |determ_sub #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) d_sub${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_sub${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DMultHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_mult${id}
        |determ_mult d_mult${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_mult${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DAddFxpHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_mult_fxp${id}
        |determ_add_fxp #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) d_add_fxp${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_add_fxp${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DSubAFxpHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_mult_fxp${id}
        |determ_suba_fxp #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) d_suba_fxp${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_suba_fxp${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DSubBFxpHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_mult_fxp${id}
        |determ_subb_fxp #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) d_subb_fxp${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_subb_fxp${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DMultFxpHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN d_mult_fxp${id}
        |determ_mult_fxp #(
        |        .BIT_WIDTH(BIT_WIDTH)
        |    ) d_mult_fxp${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END d_mult_fxp${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class FxpAddHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN f_add${id}
        |fxp_add #(
        |        .BIT_WIDTH(BIT_WIDTH)
        |    ) f_add${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END f_add${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class FxpSubHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN f_sub${id}
        |fxp_sub #(
        |        .BIT_WIDTH(BIT_WIDTH)
        |    ) f_sub${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END f_sub${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class FxpMultHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (-1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN f_mult${id}
        |fxp_mult #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) f_mult${id} (
        |        .a(${inputs(0)}),
        |        .b(${inputs(1)}),
        |        .y($output)
        |    );
        |// END f_mult${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

  class DelayBufferHandler extends NodeHandler {

    protected var id = 0
    private var netMap: Map[String, Tuple3[String, String, String]] = Map()

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN delay_buff${id}
        |delay_buffer #(
        |        .DELAY(${inputs(1)})
        |    ) delay_buff${id} (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .x(${inputs(0)}),
        |        .y($output)
        |    );
        |// END delay_buff${id}
        """.stripMargin

      id += 1
      (netList, outputString)
    }

    def createAll(): String = {
      var outStr = ""
      for ((name, (input, output, delay)) <- netMap) {
        this.create(List(input, delay), output, List(), new Netlist())
          match {case (list, str) => outStr += str}
      }

      outStr
    }

    def addPop(name: String, netName: String, size: Tuple2[Int, Int], netList: Netlist):
               Netlist = {
      // Create copy of netlist
      var newNetList = netList

      // Add wire to netlist
      newNetList.addWire(netName, size, false, false)

      // Add wire to map
      if (netMap contains name) {
        var value = netMap(name)
        netMap += (name -> (value._1, netName, value._3))
      } else netMap += (name -> ("", netName, ""))

      newNetList
    }

    def addPush(name: String, netName: String, size: Tuple2[Int, Int], netList: Netlist):
                Netlist = {
      // Create copy of netlist
      var newNetList = netList

      // Add wire to netlist
      newNetList.addWire(netName, size, false, false)

      // Add wire to map
      if (netMap contains name) {
        var value = netMap(name)
        netMap += (name -> (netName, value._2, value._3))
      } else netMap += (name -> (netName, "", ""))

      newNetList
    }

    def getBufferNames: List[String] = netMap.keySet.toList

    def setDelay(names: List[String], delays: List[String]): Unit = {
      for ((name, delay) <- (names zip delays).toMap) {
        // Set delay
        if (netMap contains name) {
          var value = netMap(name)
          netMap += (name -> (value._1, value._2, delay))
        } else netMap += (name -> ("", "", delay))
      }
    }

  }

  class SDMHandler extends NodeHandler {

    protected var id = 0

    def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
              (Netlist, String) = {
      // Create copy of netlist
      var newNetList = netList

      // Add inputs to netlist
      for ((name, size) <- (inputs zip sizes).toMap
          if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
        newNetList.addWire(name, size, false, false)
      }

      // Add outputs to netlist
      newNetList.addWire(output, (1, 1), false, false)

      // Create Verilog string
      var outputString = s"""
        |$stdComment
        |// BEGIN sdm${id}
        |sdm #(
        |        .BIT_WIDTH(BIT_WIDTH),
        |        .INT_WIDTH(INT_WIDTH)
        |    ) sdm${id} (
        |        .CLK(CLK),
        |        .nRST(nRST),
        |        .x(${inputs(0)}),
        |        .y($output)
        |    );
        |// END sdm${id}
        """.stripMargin

      id += 1
      (newNetList, outputString)
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy