Working ap1919 gv319 Symbol code.

This commit is contained in:
Giorgos Vyronos 2022-03-08 12:34:20 +00:00
parent c6e5381f61
commit 51b5cbdb32

View file

@ -1,4 +1,9 @@
(* //---------------------------------------------------------------------------------//
//--------------------AP1919 CODE SECTION STARTS-------------------------------------//
//---------------------------------------------------------------------------------//
(*
This module draws schematics component symbols. Each symbol is associated with a unique Issie component. This module draws schematics component symbols. Each symbol is associated with a unique Issie component.
*) *)
@ -13,9 +18,11 @@ open CommonTypes
open System.Text.RegularExpressions open System.Text.RegularExpressions
/// --------- STATIC VARIABLES --------- ///
/// --------- STATIC VARIABLES --------- ///
let GridSize = 30 let GridSize = 30
// let (x:ComponentType List) = [MergeWires ;(SplitWire,a);Mux2 ;NbitsAdder x; IOLabel]
/// ---------- SYMBOL TYPES ---------- /// /// ---------- SYMBOL TYPES ---------- ///
type Rotation = R0 | R90 | R180 | R270 type Rotation = R0 | R90 | R180 | R270
@ -91,8 +98,6 @@ let posAdd (a:XYPos) (b:XYPos) =
let posOf x y = {X=x;Y=y} let posOf x y = {X=x;Y=y}
// ----- helper functions for titles ----- //
//STransform Finite State Machine //STransform Finite State Machine
let stransform_fsm(prev_state:Rotation):Rotation = let stransform_fsm(prev_state:Rotation):Rotation =
match prev_state with match prev_state with
@ -101,16 +106,16 @@ let stransform_fsm(prev_state:Rotation):Rotation =
| R180 -> R270 | R180 -> R270
| R270 -> R0 | R270 -> R0
///Insert titles compatible with greater than 1 bus width // ----- helper functions for titles ----- //
let title t n =
if n = 1 then t else t + "(" + string(n-1) + "..0)"
///Insert titles for bus select let titleGen text (buswidth) =
let bustitle wob lsb = if buswidth = 1 then text else text + "(" + string(buswidth-1) + "..0)"
let bustitleGen wob lsb =
if wob <> 1 then"(" + string(wob + lsb - 1) + ".." + string(lsb) + ")" else string(lsb) if wob <> 1 then"(" + string(wob + lsb - 1) + ".." + string(lsb) + ")" else string(lsb)
///Decodes the component type into component labels ///Decodes the component type into component labels
let prefix compType = let getLabel compType =
match compType with match compType with
| Not | And | Or | Xor | Nand | Nor | Xnor -> "G" | Not | And | Or | Xor | Nand | Nor | Xnor -> "G"
| Mux2 -> "MUX" | Mux2 -> "MUX"
@ -135,28 +140,28 @@ let prefix compType =
//-----------------------------Skeleton Model Type for symbols----------------// //-----------------------------Skeleton Model Type for symbols----------------//
// Text to be put inside different Symbols depending on their ComponentType // Text to be put inside different Symbols depending on their ComponentType
let gateDecoderType (comp:Component) = let getTitle (comp:Component) =
match comp.Type with match comp.Type with
| And | Nand-> "&" | And | Nand-> "&"
| Or | Nor-> "1" | Or | Nor-> "1"
| Xor | Xnor -> "=1" | Xor | Xnor -> "=1"
| Not -> "1" | Not -> "1"
| Decode4 -> "Decode" | Decode4 -> "Decode"
| NbitsAdder n -> title "Adder" n | NbitsAdder n -> titleGen "Adder" n
| Register n | RegisterE n-> title "Register" n | Register n | RegisterE n-> titleGen "Register" n
| AsyncROM1 _ -> "Async-ROM" | AsyncROM1 _ -> "Async-ROM"
| ROM1 _ -> "Sync-ROM" | ROM1 _ -> "Sync-ROM"
| RAM1 _ -> "Sync-RAM" | RAM1 _ -> "Sync-RAM"
| AsyncRAM1 _ -> "Async-RAM" | AsyncRAM1 _ -> "Async-RAM"
| DFF -> "DFF" | DFF -> "DFF"
| DFFE -> "DFFE" | DFFE -> "DFFE"
| NbitsXor x-> title "N-bits-Xor" x | NbitsXor (x)-> titleGen "N-bits-Xor" x
| Custom x -> x.Name | Custom x -> x.Name
| _ -> "" | _ -> ""
///Helper function to create portNamesMap for custom components
let createCustomPortNamesMap inputLabels outputLabels = let customPortNamesMap inputLabels outputLabels =
let adder x (name:string,_) (portType:PortType) = let adder x ((name:string),n) (portType:PortType)=
let key = let key =
match portType with match portType with
|PortType.Input -> "I"+ string x |PortType.Input -> "I"+ string x
@ -167,9 +172,9 @@ let createCustomPortNamesMap inputLabels outputLabels =
[inputList;outputList] |> List.concat |> Map.ofList [inputList;outputList] |> List.concat |> Map.ofList
// Input and Output names of the ports depending on their ComponentType /// Input and Output names of the ports depending on their ComponentType
// returns map with (port key in APortOffsetsMap, port name) /// returns map with (port key in APortOffsetsMap, port name)
let portNameMap (comp:Component) = let portNamesMap (comp:Component) =
match comp.Type with match comp.Type with
| NbitsAdder _ -> Map [ ("I0", "Cin"); ("I1", "A"); ("I2","B");("O0","Sum");("O1","Cout") ] | NbitsAdder _ -> Map [ ("I0", "Cin"); ("I1", "A"); ("I2","B");("O0","Sum");("O1","Cout") ]
| Decode4 -> Map [ ("I0", "Sel"); ("I1", "Data"); ("O0","0");("O1","1"); ("O2","2");("O3","3") ] | Decode4 -> Map [ ("I0", "Sel"); ("I1", "Data"); ("O0","0");("O1","1"); ("O2","2");("O3","3") ]
@ -181,7 +186,7 @@ let portNameMap (comp:Component) =
| Mux2 -> Map [ ("I0", "0"); ("I1", "1"); ("I2","SEL");("O0","OUT") ] | Mux2 -> Map [ ("I0", "0"); ("I1", "1"); ("I2","SEL");("O0","OUT") ]
| Demux2 -> Map [ ("I0", "IN"); ("I1", "SEL"); ("O0","0");("O1","1") ] | Demux2 -> Map [ ("I0", "IN"); ("I1", "SEL"); ("O0","0");("O1","1") ]
| NbitsXor _ -> Map [ ("I0", "P"); ("I1", "Q"); ("O0","Out") ] | NbitsXor _ -> Map [ ("I0", "P"); ("I1", "Q"); ("O0","Out") ]
| Custom x -> createCustomPortNamesMap x.InputLabels x.OutputLabels | Custom x -> customPortNamesMap x.InputLabels x.OutputLabels
|_ -> Map.empty |_ -> Map.empty
// |Mux4 -> (["0"; "1"; "2"; "3" ;"SEL"],["OUT"]) // |Mux4 -> (["0"; "1"; "2"; "3" ;"SEL"],["OUT"])
// |Demux4 -> (["IN"; "SEL"],["0"; "1";"2"; "3";]) // |Demux4 -> (["IN"; "SEL"],["0"; "1";"2"; "3";])
@ -189,9 +194,24 @@ let portNameMap (comp:Component) =
// |Mux8 -> (["0"; "1"; "2" ; "3" ; "4" ; "5" ; "6" ; "7";"SEL"],["OUT"]) // |Mux8 -> (["0"; "1"; "2" ; "3" ; "4" ; "5" ; "6" ; "7";"SEL"],["OUT"])
// |_ -> ([],[]) // |_ -> ([],[])
// EXTENSION: Extra Components made that are not currently in Issie. Can be extended later by using this code as it is . // EXTENSION: Extra Components made that are not currently in Issie. Can be extended later by using this code as it is .
// !! They need to be in Map Format !!
/// Genererates a list of ports:
let portLists numOfPorts hostID portType =
//-----------------------Component and Symbol Creation---------------------//
///Rounds an integer to any given number. The first parameter is the number to round to, the second parameter is the input number that will be rounded
let inline roundToZ (z : int) (number : int) = //IMPLEMENT IT INSIDE ARGS??? -> DETELE IT???
number + abs((number % z) - z)
//Find the custom component's I/O label with the maximum size
let customCompMaxLabel (lst : (string * int) list) =
let labelList = List.map (fst >> String.length) lst
if List.isEmpty labelList then 0 //if a component has no inputs or outputs list max will fail
else List.max labelList
/// Genererates a component's Input/Output Port list
let portListGen numOfPorts hostID portType =
if numOfPorts < 1 if numOfPorts < 1
then [] then []
else else
@ -204,82 +224,72 @@ let portLists numOfPorts hostID portType =
HostId = hostID HostId = hostID
}]) }])
/// Helper function to initialise each type of component
//-----------------------Skeleton Message type for symbols---------------------// let createComponent (pos: XYPos) (comptype: ComponentType) (id:string) (label:string) : Component =
///Rounds an integer to any given number. The first parameter is the number to round to, the second parameter is the input number that will be rounded
let roundToN (n : int) (x : int) =
x + abs((x % n) - n)
let customToLength (lst : (string * int) list) =
let labelList = List.map (fst >> String.length) lst
if List.isEmpty labelList then 0 //if a component has no inputs or outputs list max will fail
else List.max labelList
// helper function to initialise each type of component
let makeComp (pos: XYPos) (comptype: ComponentType) (id:string) (label:string) : Component =
// function that helps avoid dublicate code by initialising parameters that are the same for all component types and takes as argument the others
let makeComponent (n, nout, h, w) label : Component=
{
Id = id
Type = comptype
Label = label
InputPorts = portLists n id PortType.Input
OutputPorts = portLists nout id PortType.Output
X = int (pos.X - float w / 2.0)
Y = int (pos.Y - float h / 2.0)
H = h
W = w
}
// match statement for each component type. the output is a 4-tuple that is used as an input to makecomponent (see below) // match statement for each component type. the output is a 4-tuple that is used as an input to makecomponent (see below)
// 4-tuple of the form ( number of input ports, number of output ports, Height, Width) // 4-tuple of the form ( number of input ports, number of output ports, Height, Width)
let args = //grid size is set at the begining
let characteristics =
match comptype with match comptype with
| ROM _ | RAM _ | AsyncROM _ -> | ROM _ | RAM _ | AsyncROM _ ->
failwithf "What? Legacy RAM component types should never occur" failwithf "What? Legacy RAM component types should never occur"
| And | Nand | Or | Nor | Xnor | Xor -> (2 , 1, 2*GridSize , 2*GridSize) | And | Nand | Or | Nor | Xnor | Xor -> (2 , 1, 2*GridSize , 2*GridSize)
| Not -> ( 1 , 1, 2*GridSize , 2*GridSize) | Not -> ( 1 , 1, 2*GridSize , 2*GridSize)
| ComponentType.Input _ -> ( 0 , 1, GridSize , 2*GridSize) | ComponentType.Input (a) -> ( 0 , 1, GridSize , 2*GridSize)
| ComponentType.Output _ -> ( 1 , 0, GridSize , 2*GridSize) | ComponentType.Output (a) -> ( 1 , 0, GridSize , 2*GridSize)
| ComponentType.Viewer _ -> ( 1 , 0, GridSize , GridSize) | ComponentType.Viewer a -> ( 1 , 0, GridSize , GridSize)
| ComponentType.IOLabel ->( 1 , 1, GridSize , 2*GridSize) | ComponentType.IOLabel ->( 1 , 1, GridSize , 2*GridSize)
| Decode4 ->( 2 , 4 , 4*GridSize , 3*GridSize) | Decode4 ->( 2 , 4 , 4*GridSize , 3*GridSize)
| Constant1 _ | Constant _ -> ( 0 , 1, GridSize , 2*GridSize) | Constant1 (a, b,_) | Constant(a, b) -> ( 0 , 1, GridSize , 2*GridSize)
| MergeWires -> ( 2 , 1, 2*GridSize , 2*GridSize) | MergeWires -> ( 2 , 1, 2*GridSize , 2*GridSize)
| SplitWire _ ->( 1 , 2 , 2*GridSize , 2*GridSize) | SplitWire (a) ->( 1 , 2 , 2*GridSize , 2*GridSize)
| Mux2 -> ( 3 , 1, 3*GridSize , 2*GridSize) | Mux2 -> ( 3 , 1, 3*GridSize , 2*GridSize)
// EXTENSION: | Mux4 -> ( 5 , 1, 5*GridSize , 2*GridSize) // EXTENSION: | Mux4 -> ( 5 , 1, 5*GridSize , 2*GridSize)
// EXTENSION: | Mux8 -> ( 9 , 1, 7*GridSize , 2*GridSize) // EXTENSION: | Mux8 -> ( 9 , 1, 7*GridSize , 2*GridSize)
| Demux2 ->( 2 , 2, 3*GridSize , 2*GridSize) | Demux2 ->( 2 , 2, 3*GridSize , 2*GridSize)
// EXTENSION: | Demux4 -> ( 2 , 4, 150 , 50) // EXTENSION: | Demux4 -> ( 2 , 4, 150 , 50)
// EXTENSION: | Demux8 -> ( 2 , 8, 200 , 50) // EXTENSION: | Demux8 -> ( 2 , 8, 200 , 50)
| BusSelection _ -> ( 1 , 1, GridSize, 2*GridSize) | BusSelection (a, b) -> ( 1 , 1, GridSize, 2*GridSize)
| BusCompare _ -> ( 1 , 1, GridSize , 2*GridSize) | BusCompare (a, b) -> ( 1 , 1, GridSize , 2*GridSize)
| DFF -> ( 1 , 1, 3*GridSize , 3*GridSize) | DFF -> ( 1 , 1, 3*GridSize , 3*GridSize)
| DFFE -> ( 2 , 1, 3*GridSize , 3*GridSize) | DFFE -> ( 2 , 1, 3*GridSize , 3*GridSize)
| Register _ -> ( 1 , 1, 3*GridSize , 4*GridSize ) | Register (a) -> ( 1 , 1, 3*GridSize , 4*GridSize )
| RegisterE _ -> ( 2 , 1, 3*GridSize , 4*GridSize) | RegisterE (a) -> ( 2 , 1, 3*GridSize , 4*GridSize)
| AsyncROM1 _ -> ( 1 , 1, 3*GridSize , 4*GridSize) | AsyncROM1 (a) -> ( 1 , 1, 3*GridSize , 4*GridSize)
| ROM1 _ -> ( 1 , 1, 3*GridSize , 4*GridSize) | ROM1 (a) -> ( 1 , 1, 3*GridSize , 4*GridSize)
| RAM1 _ | AsyncRAM1 _ -> ( 3 , 1, 3*GridSize , 4*GridSize) | RAM1 (a) | AsyncRAM1 a -> ( 3 , 1, 3*GridSize , 4*GridSize)
| NbitsXor _ -> ( 2 , 1, 3*GridSize , 4*GridSize) | NbitsXor (n) -> ( 2 , 1, 3*GridSize , 4*GridSize)
| NbitsAdder _ -> ( 3 , 2, 3*GridSize , 4*GridSize) | NbitsAdder (n) -> ( 3 , 2, 3*GridSize , 4*GridSize)
| Custom x -> | Custom x ->
let h = GridSize + GridSize * (List.max [List.length x.InputLabels; List.length x.OutputLabels]) let h = GridSize + GridSize * (List.max [List.length x.InputLabels; List.length x.OutputLabels])
let maxInLength, maxOutLength = customToLength x.InputLabels, customToLength x.OutputLabels let maxInLength, maxOutLength = customCompMaxLabel x.InputLabels, customCompMaxLabel x.OutputLabels
let maxW = maxInLength + maxOutLength + label.Length let maxW = maxInLength + maxOutLength + label.Length
let scaledW = roundToN GridSize (maxW * GridSize / 5) //Divide by 5 is just abitrary as otherwise the symbols would be too wide let scaledW = roundToZ GridSize (maxW * GridSize / 5) //Divide by 5 is just abitrary as otherwise the symbols would be too wide
let w = max scaledW (GridSize * 4) //Ensures a minimum width if the labels are very small let w = max scaledW (GridSize * 4) //Ensures a minimum width if the labels are very small
( List.length x.InputLabels, List.length x.OutputLabels, h , w) ( List.length x.InputLabels, List.length x.OutputLabels, h , w)
makeComponent args label
// Function to generate a new symbol // function that helps avoid dublicate code by initialising parameters that are the same for all component types and takes as argument the others
let createComponent' (inputPortsNo, outputPortsNo, h, w) label : Component=
{
Id = id
Type = comptype
Label = label
InputPorts = portListGen inputPortsNo id PortType.Input
OutputPorts = portListGen outputPortsNo id PortType.Output
X = int (pos.X - float w / 2.0)
Y = int (pos.Y - float h / 2.0)
H = h
W = w
}
createComponent' characteristics label
/// Function to generate a new symbol
let createNewSymbol (pos: XYPos) (comptype: ComponentType) (label:string) = let createNewSymbol (pos: XYPos) (comptype: ComponentType) (label:string) =
let id = JSHelpers.uuid () let id = JSHelpers.uuid ()
let comp = makeComp pos comptype id label let comp = createComponent pos comptype id label
{ {
Pos = { X = pos.X - float comp.W / 2.0; Y = pos.Y - float comp.H / 2.0 } Pos = { X = pos.X - float comp.W / 2.0; Y = pos.Y - float comp.H / 2.0 }
STransform = R0; STransform = R0;
@ -292,19 +302,21 @@ let createNewSymbol (pos: XYPos) (comptype: ComponentType) (label:string) =
Compo = comp Compo = comp
Opacity = 1.0 Opacity = 1.0
Moving = false Moving = false
APortOffsetsMap = Map.empty<string,PortOrientationOffset> APortOffsetsMap = Map.empty<string,PortOrientationOffset> //this is initialised as empty and then the map is added in the addsymbol function (line: )
} } //for readme: this is because the component is not a parameter of the createNewSymbol function
//and adding it requires many changes in the other section of symbol. Ofcourse it is better to have it here so maybe a TODO during group work
// Function to add ports to port model /// Function to add ports to port model
let addToPortModel (model: Model) (sym: Symbol) = let addPortsToModel (model: Model) (symbol: Symbol) =
let addOnePort (currentPorts: Map<string, Port>) (port: Port) = let addOnePort (currentPorts: Map<string, Port>) (port: Port) =
Map.add port.Id port currentPorts Map.add port.Id port currentPorts
let addedInputPorts = (model.Ports, sym.Compo.InputPorts) ||> List.fold addOnePort let addedInputPorts = (model.Ports, symbol.Compo.InputPorts) ||> List.fold addOnePort
(addedInputPorts, sym.Compo.OutputPorts) ||> List.fold addOnePort (addedInputPorts, symbol.Compo.OutputPorts) ||> List.fold addOnePort
//////////////////////KEEP ONLY SO THAT THE CODE COMPILES -> IT AFFECTS GV319'S CODE ///////////////////////////////////
//////////////////////KEEP ONLY SO THAT THE CODE COMPILES -> IT AFFECTS 2nd part of symbol (lines: 750 - END) ///////////////////////////////////
//-----------------------------------------GET PORT POSITION--------------------------------------------------- //-----------------------------------------GET PORT POSITION---------------------------------------------------
// Function that calculates the positions of the ports // Function that calculates the positions of the ports
@ -315,8 +327,8 @@ let inline getPortPosEdgeGap (ct: ComponentType) =
| _ -> 1.0 | _ -> 1.0
let getPortPos (comp: Component) (port:Port) = let getPortPos (comp: Component) (port:Port) =
let ports, posX = let (ports, posX) =
if port.PortType = PortType.Input then if port.PortType = (PortType.Input) then
(comp.InputPorts, 0.0) (comp.InputPorts, 0.0)
else else
(comp.OutputPorts, float( comp.W )) (comp.OutputPorts, float( comp.W ))
@ -327,22 +339,15 @@ let getPortPos (comp: Component) (port:Port) =
let getPortPosModel (model: Model) (port:Port) = let getPortPosModel (model: Model) (port:Port) =
getPortPos (Map.find (ComponentId port.HostId) model.Symbols).Compo port getPortPos (Map.find (ComponentId port.HostId) model.Symbols).Compo port
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------DRAWING HELPERS --------------------------------------------------- //---------------------------------------APortOffsetMap HELPERS ----------------------------------------------//
// Text adding function with many parameters (such as bold, position and text) ///Helper function to find XYPos of ports on the RHS/LHS
let private addText posX posY name txtPos weight size=
let text =
{defaultText with TextAnchor = txtPos; FontWeight = weight; FontSize = size}
[makeText posX posY name text]
/////// APORTOFFSET MAP HELPERS //////
let offsethelper (comp: Component) orientation (port:Port) = let offsethelper (comp: Component) orientation (port:Port) =
let inline getPortPosEdgeGap (ct: ComponentType) = let inline getPortPosEdgeGap (ct: ComponentType) =
match ct with match ct with
| MergeWires | SplitWire _ -> 0.25 | MergeWires | SplitWire _ -> 0.25
| _ -> 1.0 | _ -> 1.0
let ports, posX = let (ports, posX) =
if port.PortType = PortType.Input then if port.PortType = (PortType.Input) then
(comp.InputPorts, 0.0) (comp.InputPorts, 0.0)
else else
(comp.OutputPorts, float( comp.W )) (comp.OutputPorts, float( comp.W ))
@ -351,10 +356,10 @@ let offsethelper (comp: Component) orientation (port:Port) =
let posY = (float(comp.H))* (( index + gap )/( float( ports.Length ) + 2.0*gap - 1.0)) // the ports are created so that they are equidistant let posY = (float(comp.H))* (( index + gap )/( float( ports.Length ) + 2.0*gap - 1.0)) // the ports are created so that they are equidistant
{X=posX;Y=posY} {X=posX;Y=posY}
/////change name /// Helper function which creates the keys and values of the APortOffsetMap from the Input/Output Port list of component
let portListToMap (portList: Port List) (symbol: Symbol) : Map<string,PortOrientationOffset>= let portListToMap (portList: Port List) (symbol: Symbol) : Map<string,PortOrientationOffset>=
let adder (symbol: Symbol) (port: Port) = let adder (symbol: Symbol) (port: Port) =
let num = match port.PortNumber with |Some n -> n |_-> -1 let num = match port.PortNumber with |Some n -> n |_->(-1)
let key = let key =
match port.PortType with match port.PortType with
|PortType.Input -> "I"+ string num |PortType.Input -> "I"+ string num
@ -367,19 +372,19 @@ let portListToMap (portList: Port List) (symbol: Symbol) : Map<string,PortOrient
if (portList.Length) < 1 then [] |> Map.ofList if (portList.Length) < 1 then [] |> Map.ofList
else ( [0..(portList.Length-1)] |> List.collect (fun x -> (adder symbol portList[x])) ) |> Map.ofList else ( [0..(portList.Length-1)] |> List.collect (fun x -> (adder symbol portList[x])) ) |> Map.ofList
/// APortOffsetsMap generator
let genAPortOffsets (symbol: Symbol) (cType: ComponentType) : Map<string,PortOrientationOffset> = let genAPortOffsets (symbol: Symbol) (cType: ComponentType) : Map<string,PortOrientationOffset> =
//generator for MUX //generator for MUX
let genAPortOffsetsMux (symbol: Symbol) = let genAPortOffsetsMux (symbol: Symbol) =
let getPosY index = (float(symbol.Compo.H))* (( index + 1.0 )/(3.0)) let getPosY index = (float(symbol.Compo.H))* (( index + 1.0 )/(3.0))
let temp = [ ("I0", {Side=Left;Offset={X=0.0;Y=(getPosY 0.0)}});("I1", {Side=Left;Offset={X=0.0;Y=(getPosY 1.0)}});("I2", {Side=Left;Offset={X=float(symbol.Compo.W)/2.0;Y=float(symbol.Compo.H)*0.9}});("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/2.0}})] Map.ofList [ ("I0", {Side=Left;Offset={X=0.0;Y=(getPosY 0.0)}});("I1", {Side=Left;Offset={X=0.0;Y=(getPosY 1.0)}});("I2", {Side=Bottom;Offset={X=float(symbol.Compo.W)/2.0;Y=float(symbol.Compo.H)*0.9}});("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/2.0}})]
temp |> Map.ofList
//generator for NBitsAdder //generator for NBitsAdder
let genAPortOffsetsAdder (symbol: Symbol) = let genAPortOffsetsAdder (symbol: Symbol) =
let getPosY index = (float(symbol.Compo.H))* (( index + 1.0 )/(3.0)) let getPosY index = (float(symbol.Compo.H))* (( index + 1.0 )/(3.0))
let temp = [ ("I2", {Side=Left;Offset={X=0.0;Y=(getPosY 1.0)}});("I1", {Side=Left;Offset={X=0.0;Y=(getPosY 0.0)}});("I0", {Side=Bottom;Offset={X=float(symbol.Compo.W)/2.0;Y=float(symbol.Compo.H)}});("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/3.0}});("O1", {Side=Top;Offset={X=float(symbol.Compo.W)-30.0;Y=0.0}})] Map.ofList [ ("I0", {Side=Bottom;Offset={X=float(symbol.Compo.W)/3.0;Y=float(symbol.Compo.H)}});("I1", {Side=Left;Offset={X=0.0;Y=(getPosY 0.0)}}); ("I2", {Side=Left;Offset={X=0.0;Y=(getPosY 1.0)}}); ("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/3.0}});("O1", {Side=Top;Offset={X=float(symbol.Compo.W)-30.0;Y=0.0}})]
temp |> Map.ofList
//generator for everything else //generator for everything else
let genAPortOffsets' (symbol: Symbol) : Map<string,PortOrientationOffset> = let genAPortOffsets' (symbol: Symbol) : Map<string,PortOrientationOffset> =
@ -394,9 +399,23 @@ let genAPortOffsets (symbol: Symbol) (cType: ComponentType) : Map<string,PortOri
|NbitsAdder _ -> genAPortOffsetsAdder symbol |NbitsAdder _ -> genAPortOffsetsAdder symbol
|_ -> genAPortOffsets' symbol |_ -> genAPortOffsets' symbol
/// Rotates port posistion (given the symbol rotation) by updating the APortOffsetsMap
let rotatePortMap (map:Map<string,PortOrientationOffset>) (symbol:Symbol) = let rotatePortMap (map:Map<string,PortOrientationOffset>) (symbol:Symbol) =
let rotatePortMapMux (map:Map<string,PortOrientationOffset>) (symbol:Symbol) =
match symbol.STransform with
|R0 -> Map.ofList [ ("I0", {Side=Top;Offset={X=(float(symbol.Compo.H)*2.0/3.0);Y=(0.0)}});("I1", {Side=Top;Offset={X=(float(symbol.Compo.H)/3.0);Y=(0.0)}});("I2", {Side=Left;Offset={X=float(symbol.Compo.H)*0.1;Y=float(symbol.Compo.W)/2.0}});("O0", {Side=Bottom;Offset={X=float(symbol.Compo.H)/2.0;Y=float(symbol.Compo.W)}})]
|R90 -> Map.ofList [ ("I0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=(float(symbol.Compo.H)*2.0/3.0)}});("I1", {Side=Right;Offset={X=float(symbol.Compo.W);Y=(float(symbol.Compo.H)/3.0)}});("I2", {Side=Top;Offset={X=float(symbol.Compo.W)/2.0;Y=float(symbol.Compo.H)*0.1}});("O0", {Side=Left;Offset={X=0.0;Y=float(symbol.Compo.H)/2.0}})]
|R180 -> Map.ofList [ ("I0", {Side=Bottom;Offset={X=(float(symbol.Compo.H)/3.0);Y=float(symbol.Compo.W)}});("I1", {Side=Bottom;Offset={X=(float(symbol.Compo.H)*2.0/3.0);Y=float(symbol.Compo.W)}});("I2", {Side=Right;Offset={X=float(symbol.Compo.H)*0.9;Y=float(symbol.Compo.W)/2.0}});("O0", {Side=Top;Offset={X=float(symbol.Compo.H)/2.0;Y=0.0}})]
|R270 -> Map.ofList [ ("I0", {Side=Left;Offset={X=0.0;Y=(float(symbol.Compo.H)/3.0)}});("I1", {Side=Left;Offset={X=0.0;Y=(float(symbol.Compo.H)*2.0/3.0)}});("I2", {Side=Bottom;Offset={X=float(symbol.Compo.W)/2.0;Y=float(symbol.Compo.H)*0.9}});("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/2.0}})]
let rotatePortMapAdder (map:Map<string,PortOrientationOffset>) (symbol:Symbol) =
match symbol.STransform with
|R0 -> Map.ofList [ ("I0", {Side=Left;Offset={X=0.0;Y=float(symbol.Compo.W)/3.0}});("I1", {Side=Top;Offset={X=float(symbol.Compo.H)*2.0/3.0;Y=0.0}}); ("I2", {Side=Top;Offset={X=float(symbol.Compo.H)/3.0;Y=0.0}}); ("O0", {Side=Bottom;Offset={X=float(symbol.Compo.H)*2.0/3.0;Y=float(symbol.Compo.W)}});("O1", {Side=Right;Offset={X=(symbol.Compo.H);Y=float(symbol.Compo.W)-30.0}})]
|R90 -> Map.ofList [ ("I0", {Side=Top;Offset={X=float(symbol.Compo.W)*2.0/3.0;Y=0.0}});("I1", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)*2.0/3.0}}); ("I2", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/3.0}}); ("O0", {Side=Left;Offset={X=0.0;Y=float(symbol.Compo.H)*2.0/3.0}});("O1", {Side=Bottom;Offset={X=30.0;Y=float(symbol.Compo.H)}})]
|R180 -> Map.ofList [ ("I0", {Side=Right;Offset={X=float(symbol.Compo.H);Y=float(symbol.Compo.W)*2.0/3.0}});("I1", {Side=Bottom;Offset={X=float(symbol.Compo.H)/3.0;Y=float(symbol.Compo.W)}}); ("I2", {Side=Bottom;Offset={X=float(symbol.Compo.H)*2.0/3.0;Y=float(symbol.Compo.W)}}); ("O0", {Side=Top;Offset={X=float(symbol.Compo.H)/3.0;Y=0.0}});("O1", {Side=Left;Offset={X=0.0;Y=30.0}})]
|R270 -> Map.ofList [ ("I0", {Side=Bottom;Offset={X=float(symbol.Compo.W)/3.0;Y=float(symbol.Compo.H)}});("I1", {Side=Left;Offset={X=0.0;Y=float(symbol.Compo.H)/3.0}}); ("I2", {Side=Left;Offset={X=0.0;Y=float(symbol.Compo.H)*2.0/3.0}}); ("O0", {Side=Right;Offset={X=float(symbol.Compo.W);Y=float(symbol.Compo.H)/3.0}});("O1", {Side=Top;Offset={X=float(symbol.Compo.W)-30.0;Y=0.0}})]
let rotatePortMap' (map:Map<string,PortOrientationOffset>) (symbol:Symbol) = let rotatePortMap' (map:Map<string,PortOrientationOffset>) (symbol:Symbol) =
map |> Map.map (fun key port -> map |> Map.map (fun key port ->
match port.Side with match port.Side with
@ -407,27 +426,70 @@ let rotatePortMap (map:Map<string,PortOrientationOffset>) (symbol:Symbol) =
) //MUX + ADDER requires special treatment ) //MUX + ADDER requires special treatment
match symbol.Compo.Type with match symbol.Compo.Type with
|MergeWires |SplitWire _ |Mux2 |NbitsAdder _ -> map |Mux2 -> rotatePortMapMux map symbol
|NbitsAdder _ -> rotatePortMapAdder map symbol
|MergeWires |SplitWire _ -> map
|_ -> rotatePortMap' map symbol |_ -> rotatePortMap' map symbol
////////////////////// OLD IMPLEMENTATION -> NOT WORKING -> keep for readme.md //----------------------------------------ROTATION HELPERS-----------------------------------------------
let rotatePortMapOLD (map:Map<string,PortOrientationOffset>) (symbol:Symbol) = ///Symbol Points rotation function
let h,w = let rotatePoints points rotation =
match symbol.STransform with let rotate90 points =
|R0|R180 -> symbol.Compo.H, symbol.Compo.W match points with
|R90|R270 -> symbol.Compo.W, symbol.Compo.H |[x1;y1;x2;y2;x3;y3] -> [y1;x1;y2;x2;y3;x3] //constant
map |> Map.map (fun key port -> |[x1;y1;x2;y2;x3;y3;x4;y4] -> [y1;x1;y2;x2;y3;x3;y4;x4] //all basic symbols
match port.Side with |[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[y1;x1;y5;x5;y4;x4;y3;x3;y2;x2] //input,output,wire viewer
|Right -> {Side=Bottom;Offset={X=port.Offset.Y;Y=port.Offset.X}} |[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6] -> [y6;x6;y5;x5;y4;x4;y3;x3;y2;x2;y1;x1] //Wire label
// |1 -> {Side=2;Offset={X=0.0;Y=port.Offset.X}} |[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6;x7;y7;x8;y8] -> [y1;x1;y8;x8;y7;x7;y6;x6;y5;x5;y4;x4;y3;x3;y2;x2] //bus selector/comparator
|Bottom -> {Side=Left;Offset={X=float(w)-port.Offset.Y;Y=port.Offset.X}} |_->points
|Left -> {Side=Top;Offset={X=port.Offset.Y;Y=port.Offset.X}}
|Top -> {Side=Right;Offset={X=float(w)-port.Offset.Y;Y=port.Offset.X}} let rotate180 points =
// |3 -> {Side=0;Offset={X=float(symbol.Compo.W);Y=port.Offset.X}} match points with
) //mux requires special treatment |[x1;y1;x2;y2;x3;y3] -> [x2+x2;y1;x1+x2;y2;x2+x2;y3] //constant
////////////////////////////////////////////////////////// |[x1;y1;x2;y2;x3;y3;x4;y4] -> [x1;y2;x2;y1;x3;y4;x4;y3] //all basic symbols
let newDrawPorts (portMap: Map<string,PortOrientationOffset>) o (showInput:bool) (showOutput:bool) (symbol: Symbol) : ReactElement List= |[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[x3-x2;y1;x3;y2;x3;y4;x3-x2;y5;x1;y3] //input,output, wire viewer
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6] -> [x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6] //wire label
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6;x7;y7;x8;y8] -> [x1;y4;x4-x3;y3;x4-x2;y2;x4;y1;x5;y8;x5-x7;y7;x5-x6;y6;x8;y5] //bus selector/comparator
|_->points
let rotate270 points =
match points with
|[x1;y1;x2;y2;x3;y3] -> [x2/2.0;y3;x2;y3+y3;x1;y3+y3] //constant
|[x1;y1;x2;y2;x3;y3;x4;y4] -> [y2;x1;y3;x4;y4;x3;y1;x2] //all basic symbols
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[y3;0.0;y5;x3-x2;y4;x3;y1;x3;y2;x3-x2] //input,output, wire viewer
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6] -> [y6;x6;y5;x5;y4;x4;y3;x3;y2;x2;y1;x1] //wire label
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5;x6;y6;x7;y7;x8;y8] -> [y5;x8;y6;x5-x6;y7;x5-x7;y8;x4;y1;x5;y1;x4-x2;y3;x4-x3;y4;x1] //bus selector/comparator
|_->points
match rotation with
|R0 -> points
|R90 -> rotate90 points
|R180 -> rotate180 points
|R270 -> rotate270 points
//------------------------------DRAWING SYMBOL HELPERS-------------------------------------
///convert list of points to a concatenated string to use when drawing ReactElements
let getPointsString coordList =
let rec combine lst =
match lst with
| fst::snd::tl -> (fst.ToString()+",") :: (snd.ToString()+" ") :: (combine tl)
|[_] -> []
|[] -> []
combine coordList |> String.concat ""
/// Text adding function with many parameters (such as bold, position and text)
let private addText posX posY name txtPos weight size=
let text =
{defaultText with TextAnchor = txtPos; FontWeight = weight; FontSize = size}
[makeText posX posY name text]
///Draw all ports contained in the APortOffsetMap
let DrawPorts (portMap: Map<string,PortOrientationOffset>) o (showInput:bool) (showOutput:bool) (symbol: Symbol) : ReactElement List=
if Map.isEmpty portMap then [] if Map.isEmpty portMap then []
else else
let mid = portMap |> Map.map (fun key port -> let mid = portMap |> Map.map (fun key port ->
@ -436,14 +498,14 @@ let newDrawPorts (portMap: Map<string,PortOrientationOffset>) o (showInput:bool)
) )
mid |> Map.toList |> List.map snd mid |> Map.toList |> List.map snd
///Draw the corresponding text of all ports contained in APortOffsetMap
let newDrawPortsText (portMap:Map<string,PortOrientationOffset>) (comp: Component) symbol orientation = let DrawPortsText (portMap:Map<string,PortOrientationOffset>) (comp: Component) symbol orientation =
let namesM = portNameMap comp let namesM = portNamesMap comp
if (Map.isEmpty portMap || Map.isEmpty namesM) then [] if (Map.isEmpty portMap || Map.isEmpty namesM) then []
else else
let inline charToInt c = int c - int '0' let inline charToInt c = int c - int '0'
let mid = portMap |> Map.map (fun key port -> let mid = portMap |> Map.map (fun key port ->
let name = namesM[key] let name = namesM[key] //TODO: Add error handling with Tryfind key
match port.Side with match port.Side with
|Right-> (addText (port.Offset.X-5.0) (port.Offset.Y-7.0) name "end" "normal" "12px")[0] //[0] to extract react element from list |Right-> (addText (port.Offset.X-5.0) (port.Offset.Y-7.0) name "end" "normal" "12px")[0] //[0] to extract react element from list
|Bottom -> (addText (port.Offset.X) (port.Offset.Y-20.0) name "Middle" "normal" "12px")[0] //they are added in a list at the end |Bottom -> (addText (port.Offset.X) (port.Offset.Y-20.0) name "Middle" "normal" "12px")[0] //they are added in a list at the end
@ -452,48 +514,6 @@ let newDrawPortsText (portMap:Map<string,PortOrientationOffset>) (comp: Componen
mid |> Map.toList |> List.map snd mid |> Map.toList |> List.map snd
//------------------------------HELPER FUNCTIONS FOR DRAWING SYMBOLS-------------------------------------
let rotatePoints points rotation =
let rotate90 points =
match points with
|[x1;y1;x2;y2;x3;y3;x4;y4] -> [y1;x1;y2;x2;y3;x3;y4;x4]
|[x1;y1;x2;y2;x3;y3] -> [y1;x1;y2;x2;y3;x3]
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[y1;x1;y5;x5;y4;x4;y3;x3;y2;x2]
|_->points
//TO ADD OTHER SYMBOLS AS WELL
let rotate180 points =
match points with
|[x1;y1;x2;y2;x3;y3;x4;y4] -> [x1;y2;x2;y1;x3;y4;x4;y3]
|[x1;y1;x2;y2;x3;y3] -> [x2+x2;y1;x1+x2;y2;x2+x2;y3]
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[x3-x2;y1;x3;y2;x3;y4;x3-x2;y5;x1;y3] //input,output
|_->points
//TO ADD OTHER SYMBOLS AS WELL
let rotate270 points =
match points with
|[x1;y1;x2;y2;x3;y3;x4;y4] -> [y2;x1;y3;x4;y4;x3;y1;x2]
|[x1;y1;x2;y2;x3;y3] -> [x2/2.0;y3;x2;y3+y3;x1;y3+y3]
|[x1;y1;x2;y2;x3;y3;x4;y4;x5;y5] ->[y3;0.0;y5;x3-x2;y4;x3;y1;x3;y2;x3-x2] //input,output
|_->points
//TO ADD OTHER SYMBOLS AS WELL
match rotation with
|R0 -> points
|R90 -> rotate90 points
|R180 -> rotate180 points
|R270 -> rotate270 points
let getPointsString coordList =
let rec combine lst =
match lst with
| fst::snd::tl -> (fst.ToString()+",") :: (snd.ToString()+" ") :: (combine tl)
|[_] -> []
|[] -> []
combine coordList |> String.concat ""
let private createPolygon points colour opacity = let private createPolygon points colour opacity =
[makePolygon points {defaultPolygon with Fill = colour; FillOpacity = opacity}] [makePolygon points {defaultPolygon with Fill = colour; FillOpacity = opacity}]
@ -504,15 +524,26 @@ let createBiColorPolygon points colour strokeColor opacity strokeWidth=
[makePolygon points {defaultPolygon with Fill = colour; FillOpacity = opacity; StrokeWidth = strokeWidth}] [makePolygon points {defaultPolygon with Fill = colour; FillOpacity = opacity; StrokeWidth = strokeWidth}]
let addClock posX posY colour opacity = let drawClock w h rotation colour opacity =
let points = (sprintf "%i,%i %i,%i %i,%i" posX (posY-1) (posX+8) (posY-7) posX (posY-13)) let clocktext w h rotation =
createPolygon points colour opacity match rotation with
|> List.append (addText (float(posX+10)) (float(posY-13)) " clk" "start" "normal" "12px") |R0 -> addText (10.0) (h-13.0) " clk" "start" "normal" "12px"
|R90 -> addText (8.0) (10.0) " clk" "middle" "normal" "12px"
|R180 -> addText (w-10.0) (0.0) " clk" "end" "normal" "12px"
|R270 -> addText (h-8.0) (w-20.0) " clk" "middle" "normal" "12px"
let clockpoints =
match rotation with
|R0 -> [0.0;h-1.0;8.0;h-7.0;0.0;h-13.0]
|R90 -> [(1.0);(0.0);(7.0);(8.0);(13.0);(0.0)]
|R180 -> [w;(1.0);w-8.0;(7.0);w;(13.0)]
|R270 -> [(h-1.0);w;(h-7.0);(w-8.0);(h-13.0);w]
createPolygon (getPointsString clockpoints) colour opacity
|> List.append (clocktext w h rotation)
let addInvertorNew w h rotation colour opacity = let addInvertor w h rotation colour opacity =
// let points = (sprintf "%i,%i %i,%i %i,%i" posX (posY) (posX+9) (posY) posX (posY-8))
// let w,h = float(width),float(height)
let points = let points =
match rotation with match rotation with
|R0 -> [w;h/2.0;w+9.0;h/2.0;w;h/2.0-8.0] |R0 -> [w;h/2.0;w+9.0;h/2.0;w;h/2.0-8.0]
@ -521,8 +552,8 @@ let addInvertorNew w h rotation colour opacity =
|R270 -> [w/2.0;0.0;w/2.0;(-9.0);w/2.0-8.0;0.0] |R270 -> [w/2.0;0.0;w/2.0;(-9.0);w/2.0-8.0;0.0]
createPolygon (getPointsString points) colour opacity createPolygon (getPointsString points) colour opacity
let addConstantLineNew w h rotation opacity =
// let points = (sprintf "%i,%f %i,%f" posX1 posY posX2 posY) let addConstantLine w h rotation opacity =
let points = let points =
match rotation with match rotation with
|R0 -> [w/2.0;h/2.0;w;h/2.0] |R0 -> [w/2.0;h/2.0;w;h/2.0]
@ -531,13 +562,15 @@ let addConstantLineNew w h rotation opacity =
|R270 -> [w/2.0;h/2.0;w/2.0;0.0] |R270 -> [w/2.0;h/2.0;w/2.0;0.0]
createPolygon (getPointsString points) "lightgray" opacity createPolygon (getPointsString points) "lightgray" opacity
let drawGateType w h comp = let drawGateType w h comp =
let gType = gateDecoderType comp let gType = getTitle comp
let posX,posY = let posX,posY =
match comp.Type with match comp.Type with
|_ -> (w/2.0), (h/2.0 - 7.0) |_ -> (w/2.0), (h/2.0 - 7.0)
addText posX posY gType "middle" "bold" "14px" addText posX posY gType "middle" "bold" "14px"
let outlineColor (color:string) = let outlineColor (color:string) =
match color.ToLower() with match color.ToLower() with
| "lightgray" | "lightgrey" -> "black" | "lightgray" | "lightgrey" -> "black"
@ -552,44 +585,22 @@ let addHorizontalColorLine posX1 posX2 posY opacity (color:string) = // TODO: Li
let drawLabel label width height rotation = let drawLabel label width height rotation =
match rotation with match rotation with
|R0 -> addText (width/2.0) (-20.0) (label) "middle" "normal" "16px" |R0 -> addText (width/2.0) (-20.0) (label) "middle" "normal" "16px"
|R90 -> addText (width+5.0) (height/2.0 - 8.0) label "Start" "normal" "16px" |R90 -> addText (width+5.0) (height/2.0 - 8.0) label "Start" "normal" "16px"
|R180 -> addText (width/2.0) (height+10.0) (label) "middle" "normal" "16px" |R180 -> addText (width/2.0) (height+10.0) (label) "middle" "normal" "16px"
|R270 -> addText (-5.0) (height/2.0 - 8.0) label "End" "normal" "16px" |R270 -> addText (-5.0) (height/2.0 - 8.0) label "End" "normal" "16px"
/// --------------------------------------- SYMBOL DRAWING ------------------------------------------------------ /// /// --------------------------------------- SYMBOL DRAWING ------------------------------------------------------ ///
let compSymbol (symbol:Symbol) (comp:Component) (colour:string) (showInputPorts:bool) (showOutputPorts:bool) (opacity: float)= let drawSymbol (symbol:Symbol) (comp:Component) (colour:string) (showInputPorts:bool) (showOutputPorts:bool) (opacity: float)=
// match comp.Type with
// | Input (x) -> drawInput comp x comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | Output (x) -> drawInput comp x comp.H comp.W ((symbol.STransform+2)%4) colour opacity showInputPorts showOutputPorts symbol
// | Mux2 -> drawMux comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | Demux2 -> drawDemux comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | NbitsAdder _ -> drawBasic comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | Viewer (x) -> drawViewer comp x comp.H comp.W ((symbol.STransform+2)%4) colour opacity showInputPorts showOutputPorts symbol
// | Decode4 | NbitsXor _ | NbitsAdder _ -> drawBasic comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | And | Or |Xor -> drawBasic comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | Nand | Nor | Not | Xnor -> drawBasicInverted comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// | BusSelection _ |BusCompare _ -> drawBus comp comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// |Constant1 (_,_,txt) -> drawConstant comp txt comp.H comp.W (symbol.STransform) colour opacity showInputPorts showOutputPorts symbol
// |_ -> []
// | _ -> []
// | _ -> []
let h = (comp.H) let h = float(comp.H) //height
let w = (comp.W) let w = float(comp.W) //width
let halfW = (comp.W/2)
let halfH = (comp.H/2)
let hF = float(comp.H) //float representation of height
let wF = float(comp.W) //float representation of width
let halfWF = float(comp.W/2) //float representation of halfWidth
let halfHF = float(comp.H/2) //float representation of halfHeight
let rotation = symbol.STransform let rotation = symbol.STransform
let hR,wR = match symbol.STransform with |R90|R270 -> w,h |_ -> h,w let hR,wR = match symbol.STransform with |R90|R270 -> w,h |_ -> h,w //new height,width after rotation
let mergeSplitLine posX1 posX2 posY msb lsb = let mergeSplitLine posX1 posX2 posY msb lsb =
let text = let text =
@ -600,26 +611,28 @@ let compSymbol (symbol:Symbol) (comp:Component) (colour:string) (showInputPorts:
addHorizontalColorLine posX1 posX2 (posY*float(h)) opacity colour @ addHorizontalColorLine posX1 posX2 (posY*float(h)) opacity colour @
addText (float (posX1 + posX2)/2.0) (posY*float(h)-11.0) text "middle" "bold" "9px" addText (float (posX1 + posX2)/2.0) (posY*float(h)-11.0) text "middle" "bold" "9px"
// Points that specify each symbol
let points = // Points that specify each symbol let points =
match comp.Type with match comp.Type with
| Input _ -> rotatePoints [0.0; 0.0; (float(w)*(0.66)); 0.0; float(w); float(h)/2.0; (float(w)*(0.66)); float(h); 0.0; float(h)] rotation | Input _ -> rotatePoints [0.0; 0.0; (w*0.66); 0.0; w; h/2.0; (w*0.66); h; 0.0; h] rotation
| Constant1 _ -> rotatePoints [0.0; 0.0; float(w)/2.0; float(h)/2.0; 0.0; float(h)] rotation | Constant1 _ -> rotatePoints [0.0; 0.0; (w/2.0); (h/2.0); 0.0; h] rotation
| IOLabel -> rotatePoints [float(w)*(0.33); 0.0; 0.0; float(h)/2.0; (float(w)*(0.33)); float(h); (float(w)*(0.66)); float(h); float(w); float(h)/2.0; (float(w)*(0.66)); 0.0] rotation | IOLabel -> rotatePoints [(w*0.33); 0.0; (w*0.66); 0.0; w; (h/2.0); (w*0.66); h; (w*0.33); h; 0.0; (h/2.0)] rotation
| Output _ -> rotatePoints [0.0; 0.0; (float(w)*(0.66)); 0.0; float(w); float(h)/2.0; (float(w)*(0.66)); float(h); 0.0; float(h)] (stransform_fsm(stransform_fsm(rotation))) //hack for rotation to work | Output _ -> rotatePoints [0.0; 0.0; (w*0.66); 0.0; w; (h/2.0); (w*0.66); h; 0.0; h] (stransform_fsm(stransform_fsm(rotation))) //hack for rotation to work -> same as input but rotated twice
| Viewer _ -> rotatePoints [0.0; 0.0; (float(w)*(0.8)); 0.0; float(w); float(h)/2.0; (float(w)*(0.8)); float(h); 0.0; float(h)] (stransform_fsm(stransform_fsm(rotation))) //hack for rotation to work | Viewer _ -> rotatePoints [0.0; 0.0; (w*0.8); 0.0; w; (h/2.0); (w*0.8); h; 0.0; h] (stransform_fsm(stransform_fsm(rotation))) //hack for rotation to work -> same as input (resized) but rotated twice
| MergeWires -> [halfWF; ((1.0/6.0)*(hF)); halfWF; ((5.0/6.0)*(hF))] | MergeWires -> [(w/2.0); ((1.0/6.0)*h); (w/2.0); ((5.0/6.0)*h)] //add it to rotatePoints function when implemented
| SplitWire _ -> [halfWF; ((1.0/6.0)*(hF)); halfWF; ((5.0/6.0)*(hF)); 0.0] | SplitWire _ -> [(w/2.0); ((1.0/6.0)*h); (w/2.0); ((5.0/6.0)*h); 0.0] //add it to rotatePoints function when implemented
| Demux2 -> rotatePoints [0.0; (float(h)*0.2); float(w); 0.0; float(w); float(h); 0.0; (float(h)*0.8)] rotation | Demux2 -> rotatePoints [0.0; (h*0.2); w; 0.0; w; h; 0.0; (h*0.8)] rotation
| Mux2 -> rotatePoints [0.0; 0.0; float(w); (float(h)*0.2); float(w); (float(h)*0.8); 0.0; float(h)] rotation | Mux2 -> rotatePoints [0.0; 0.0; w; (h*0.2); w; (h*0.8); 0.0; h] rotation
// EXTENSION: |Mux4|Mux8 ->(sprintf "%i,%i %i,%f %i,%f %i,%i" 0 0 w (float(h)*0.2) w (float(h)*0.8) 0 h ) // EXTENSION: |Mux4|Mux8 ->(sprintf "%i,%i %i,%f %i,%f %i,%i" 0 0 w (float(h)*0.2) w (float(h)*0.8) 0 h )
// EXTENSION: | Demux4 |Demux8 -> (sprintf "%i,%f %i,%f %i,%i %i,%i" 0 (float(h)*0.2) 0 (float(h)*0.8) w h w 0) // EXTENSION: | Demux4 |Demux8 -> (sprintf "%i,%f %i,%f %i,%i %i,%i" 0 (float(h)*0.2) 0 (float(h)*0.8) w h w 0)
| BusSelection _ |BusCompare _ -> rotatePoints [0.0; 0.0; 0.0; float(h); (0.6*(float(w))); float(h); (0.8*(float(w))); (0.7*(float(h))); float(w); (0.7*(float(h))); float(w); (0.3*(float(h))); (0.8*(float(w))); (0.3*(float(h))); (0.6*(float(w))); 0.0] rotation | BusSelection _ |BusCompare _ -> rotatePoints [0.0; 0.0; (0.6*w); 0.0; (0.8*w); (0.3*h); w; (0.3*h); w; (0.7*h); (0.8*w); (0.7*h); (0.6*w); h; 0.0; h] rotation
| _ -> rotatePoints [0.0; 0.0; float(w); 0.0; float(w); float(h); 0.0; float(h)] rotation | _ -> rotatePoints [0.0; 0.0; w; 0.0; w; h; 0.0; h] rotation
let additions = // Helper function to add certain characteristics on specific symbols (inverter, enables, clocks)
// Helper function to add certain characteristics on specific symbols (inverter, enables, clocks)
let extras =
match comp.Type with match comp.Type with
| Constant1 (_,_,txt) -> (addConstantLineNew (float(wR)) (float(hR)) rotation opacity @ addText (float (float(w)/2.0)-5.0) (float(h)-8.0) txt "middle" "normal" "12px") | Constant1 (_,_,txt) -> (addConstantLine (float(wR)) (float(hR)) rotation opacity @ addText (float (float(w)/2.0)-5.0) (float(h)-8.0) txt "middle" "normal" "12px")
| Nand | Nor | Xnor |Not -> (addInvertorNew (float(wR)) (float(hR)) rotation colour opacity) | Nand | Nor | Xnor |Not -> (addInvertor (float(wR)) (float(hR)) rotation colour opacity)
| MergeWires -> | MergeWires ->
let lo, hi = let lo, hi =
match symbol.InWidth0, symbol.InWidth1 with match symbol.InWidth0, symbol.InWidth1 with
@ -628,38 +641,38 @@ let compSymbol (symbol:Symbol) (comp:Component) (colour:string) (showInputPorts:
let msb = hi + lo - 1 let msb = hi + lo - 1
let midb = lo let midb = lo
let midt = lo - 1 let midt = lo - 1
mergeSplitLine 0 halfW (1.0/6.0) midt 0 @ mergeSplitLine 0 (int(w/2.0)) (1.0/6.0) midt 0 @
mergeSplitLine 0 halfW (5.0/6.0) msb midb @ mergeSplitLine 0 (int(w/2.0)) (5.0/6.0) msb midb @
mergeSplitLine halfW w 0.5 msb 0 mergeSplitLine (int(w/2.0)) (int(w)) 0.5 msb 0
| SplitWire mid -> | SplitWire mid ->
let msb, mid' = match symbol.InWidth0 with | Some n -> n - 1, mid | _ -> -100, -50 let msb, mid' = match symbol.InWidth0 with | Some n -> n - 1, mid | _ -> -100, -50
let midb = mid' let midb = mid'
let midt = mid'-1 let midt = mid'-1
mergeSplitLine halfW w (1.0/6.0) midt 0 @ mergeSplitLine (int(w/2.0)) (int(w)) (1.0/6.0) midt 0 @
mergeSplitLine halfW w (5.0/6.0) msb midb @ mergeSplitLine (int(w/2.0)) (int(w)) (5.0/6.0) msb midb @
mergeSplitLine 0 halfW 0.5 msb 0 mergeSplitLine 0 (int(w/2.0)) 0.5 msb 0
| DFF |DFFE -> (addClock 0 h colour opacity) | DFF |DFFE -> (drawClock w h rotation colour opacity)
| Register _ |RegisterE _ -> (addClock 0 h colour opacity) | Register _ |RegisterE _ -> (drawClock w h rotation colour opacity)
| ROM1 _ |RAM1 _ | AsyncRAM1 _ -> (addClock 0 h colour opacity) | ROM1 _ |RAM1 _ | AsyncRAM1 _ -> (drawClock w h rotation colour opacity)
| BusSelection(x,y) -> (addText (float(wR/2)-5.0) ((float(hR)/2.7)-2.0) (bustitle x y) "middle" "normal" "12px") | BusSelection(x,y) -> (addText (wR/2.0) ((hR/2.7)-2.0) (bustitleGen x y) "middle" "normal" "12px")
| BusCompare (_,y) -> (addText (float(wR/2)-6.0) (float(hR)/2.7-1.0) ("=" + NumberHelpers.hex(int y)) "middle" "bold" "10px") | BusCompare (_,y) -> (addText (wR/2.0) ((hR/2.7)-1.0) ("=" + NumberHelpers.hex(int y)) "middle" "bold" "10px")
| Input x -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") | Input (x) -> (addText (wR/2.0) (hR/3.0) (titleGen "" x) "middle" "normal" "12px")
| Output x -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") | Output (x) -> (addText (wR/2.0) ((float(hR)/3.0)) (titleGen "" x) "middle" "normal" "12px")
| Viewer x -> (addText (float(w/2)) ((float(h)/2.7)-1.25) (title "" x) "middle" "normal" "9px") | Viewer (x) -> (addText (w/2.0) ((float(h)/2.7)-1.25) (titleGen "" x) "middle" "normal" "9px")
| _ -> [] | _ -> []
let olColour, strokeWidth = let borderColour, strokeWidth =
match comp.Type with match comp.Type with
| SplitWire _ | MergeWires -> outlineColor colour, "2.0" | SplitWire _ | MergeWires -> outlineColor colour, "2.0"
| _ -> "black", "1.0" | _ -> "black", "1.0"
// Put everything together // Put everything together
(newDrawPorts symbol.APortOffsetsMap symbol.STransform showInputPorts showOutputPorts symbol) (DrawPorts symbol.APortOffsetsMap symbol.STransform showInputPorts showOutputPorts symbol) //Ports
|> List.append (newDrawPortsText symbol.APortOffsetsMap comp symbol symbol.STransform) |> List.append (DrawPortsText symbol.APortOffsetsMap comp symbol symbol.STransform) //PortsText
|> List.append (drawGateType (float(wR)) (float(hR)) comp) |> List.append (drawGateType (float(wR)) (float(hR)) comp) //Symbol Title - e.g. N-Bits-Adder(3..0)
|> List.append (additions) |> List.append (extras) //extra components required for specific symbol - e.g. Clock invertor etc.
|> List.append (drawLabel comp.Label (float(wR)) (float(hR)) symbol.STransform) |> List.append (drawLabel comp.Label (float(wR)) (float(hR)) symbol.STransform) //Label
|> List.append (createBiColorPolygon (getPointsString points) colour olColour opacity "1.0") |> List.append (createBiColorPolygon (getPointsString points) colour borderColour opacity "1.0") //actual symbol
let init () = let init () =
{ Symbols = Map.empty; CopiedSymbols = Map.empty; Ports = Map.empty ; InputPortsConnected= Set.empty ; OutputPortsConnected = Map.empty}, Cmd.none { Symbols = Map.empty; CopiedSymbols = Map.empty; Ports = Map.empty ; InputPortsConnected= Set.empty ; OutputPortsConnected = Map.empty}, Cmd.none
@ -679,14 +692,14 @@ let private renderSymbol =
fun (props : RenderSymbolProps) -> fun (props : RenderSymbolProps) ->
let symbol = props.Symbol let symbol = props.Symbol
let ({X=fX; Y=fY}:XYPos) = symbol.Pos let ({X=fX; Y=fY}:XYPos) = symbol.Pos
g ([ Style [ Transform(sprintf "translate(%fpx, %fpx)" fX fY) ] ]) (compSymbol props.Symbol props.Symbol.Compo symbol.Colour symbol.ShowInputPorts symbol.ShowOutputPorts symbol.Opacity) g ([ Style [ Transform(sprintf "translate(%fpx, %fpx)" fX fY) ] ]) (drawSymbol props.Symbol props.Symbol.Compo symbol.Colour symbol.ShowInputPorts symbol.ShowOutputPorts symbol.Opacity)
, "Symbol" , "Symbol"
, equalsButFunctions , equalsButFunctions
) )
/// View function for symbol layer of SVG /// View function for symbol layer of SVG
let MapsIntoLists map = let getSymbols map =
let listMoving = let listMoving =
Map.filter (fun _ sym -> not sym.Moving) map Map.filter (fun _ sym -> not sym.Moving) map
|>Map.toList |>Map.toList
@ -701,7 +714,7 @@ let MapsIntoLists map =
let view (model : Model) (dispatch : Msg -> unit) = let view (model : Model) (dispatch : Msg -> unit) =
let start = TimeHelpers.getTimeMs() let start = TimeHelpers.getTimeMs()
model.Symbols model.Symbols
|> MapsIntoLists |> getSymbols
|> List.map (fun ({Id = ComponentId id} as symbol) -> |> List.map (fun ({Id = ComponentId id} as symbol) ->
renderSymbol renderSymbol
{ {
@ -714,7 +727,9 @@ let view (model : Model) (dispatch : Msg -> unit) =
|> TimeHelpers.instrumentInterval "SymbolView" start |> TimeHelpers.instrumentInterval "SymbolView" start
//---------------------------------------------------------------------------------//
//--------------------AP1919 CODE SECTION ENDS-------------------------------------//
//---------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------// //---------------------------------------------------------------------------------//
//--------------------GV319 CODE SECTION 2 STARTS-------------------------------------// //--------------------GV319 CODE SECTION 2 STARTS-------------------------------------//
//---------------------------------------------------------------------------------// //---------------------------------------------------------------------------------//
@ -984,7 +999,7 @@ let labelGenNumber (model: Model) (compType: ComponentType) (label : string) =
///Generates the label for a component type ///Generates the label for a component type
let generateLabel (model: Model) (compType: ComponentType) : string = let generateLabel (model: Model) (compType: ComponentType) : string =
labelGenNumber model compType (prefix compType) labelGenNumber model compType (getLabel compType)
/// Interface function to paste symbols. Is a function instead of a message because we want an output /// Interface function to paste symbols. Is a function instead of a message because we want an output
/// Currently drag-and-drop /// Currently drag-and-drop
@ -997,13 +1012,13 @@ let pasteSymbols (symModel: Model) (mPos: XYPos) : Model * ComponentId list =
let pastedSymbol = let pastedSymbol =
{ oldSymbol with { oldSymbol with
Id = ComponentId newId Id = ComponentId newId
Compo = makeComp newPos oldSymbol.Compo.Type newId (labelGenNumber { symModel with Symbols = currSymbolModel.Symbols } oldSymbol.Compo.Type oldSymbol.Compo.Label) // TODO: Change label later Compo = createComponent newPos oldSymbol.Compo.Type newId (labelGenNumber { symModel with Symbols = currSymbolModel.Symbols } oldSymbol.Compo.Type oldSymbol.Compo.Label) // TODO: Change label later
Pos = newPos Pos = newPos
ShowInputPorts = false ShowInputPorts = false
ShowOutputPorts = false } ShowOutputPorts = false }
let newSymbolMap = currSymbolModel.Symbols.Add ((ComponentId newId), pastedSymbol) // List needs to be in this order let newSymbolMap = currSymbolModel.Symbols.Add ((ComponentId newId), pastedSymbol) // List needs to be in this order
let newPorts = addToPortModel currSymbolModel pastedSymbol let newPorts = addPortsToModel currSymbolModel pastedSymbol
{ currSymbolModel with Symbols = newSymbolMap; Ports = newPorts }, pastedIdsList @ [ pastedSymbol.Id ] { currSymbolModel with Symbols = newSymbolMap; Ports = newPorts }, pastedIdsList @ [ pastedSymbol.Id ]
let oldSymbolsList = let oldSymbolsList =
@ -1058,7 +1073,7 @@ let getEquivalentCopiedPorts (model: Model) copiedIds pastedIds (InputPortId cop
let addSymbol (model: Model) pos compType lbl = let addSymbol (model: Model) pos compType lbl =
let newSym = createNewSymbol pos compType lbl let newSym = createNewSymbol pos compType lbl
let newSymbolWithMap = {newSym with APortOffsetsMap = (genAPortOffsets newSym newSym.Compo.Type)} let newSymbolWithMap = {newSym with APortOffsetsMap = (genAPortOffsets newSym newSym.Compo.Type)}
let newPorts = addToPortModel model newSymbolWithMap let newPorts = addPortsToModel model newSymbolWithMap
let newSymModel = Map.add newSymbolWithMap.Id newSymbolWithMap model.Symbols let newSymModel = Map.add newSymbolWithMap.Id newSymbolWithMap model.Symbols
{ model with Symbols = newSymModel; Ports = newPorts }, newSymbolWithMap.Id { model with Symbols = newSymModel; Ports = newPorts }, newSymbolWithMap.Id
@ -1230,7 +1245,7 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> =
let xyPos = {X = float comp.X; Y = float comp.Y} let xyPos = {X = float comp.X; Y = float comp.Y}
let h,w = let h,w =
if comp.H = -1 && comp.W = -1 then if comp.H = -1 && comp.W = -1 then
let comp' = makeComp xyPos comp.Type comp.Id comp.Label let comp' = createComponent xyPos comp.Type comp.Id comp.Label
comp'.H,comp'.W comp'.H,comp'.W
else else
comp.H, comp.W comp.H, comp.W
@ -1258,7 +1273,7 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> =
|> Map.ofList |> Map.ofList
let folder currModel sym = let folder currModel sym =
{ currModel with Ports = addToPortModel currModel sym } { currModel with Ports = addPortsToModel currModel sym }
let newModel = ( model, symbolList ) ||> List.fold folder let newModel = ( model, symbolList ) ||> List.fold folder
{ newModel with Symbols = symbolMap }, Cmd.none { newModel with Symbols = symbolMap }, Cmd.none