@startuml
skinparam monochrome true
skinparam classAttributeIconSize 0
skinparam nodesep 110

package Model {
  package Machine {
    class BullGamma {
      _memoryMode
      ms1
      msb
      md : hexa
      BullGamma()
      selectOctad(id)
      getMemory(id)
      getOctad(id)
      getMemoryMode()
      setMemoryMode(newMode)
    }

    abstract class Serie {
      id
      Serie(id, bullGamma)
      {abstract} getInstruction(index)
    }

    class Octad {
      id
      Octad(id, memories)
      getMemory(idx)
    }

    class Memory {
      id
      blocks : Array<hexa>
      Memory(id, bullGamma)
      Memory(id, maxValue)
      getMode()
      setToZero(from, to)
      copyBlockValues(other, from, to)
      setBlockValue(idx, value)
      shiftLeft()
      shiftRight()
      compareTo(other, from, to)
      add(other, from, to)
      addValue(value, at)
      subtract(other, from, to)
      getDecimalValue(from, to) : int
      setDecimalValue(value, from, to)
    }

    class CmpMemory {
      greater: boolean
      equal: boolean
      isLower()
      isLowerOrEqual()
      isEqual()
      isNotEqual()
      isGreaterOrEqual()
      isGreater()
    }

    class MagneticDrum {
      MagneticDrum(bullGamma)
      setContent(hexCode)
      setCommutedGroup(id)
    }

    class DrumTrackGroup {
      id
      DrumTrackGroup(id, drum)
    }

    MagneticDrum "drum" *-- "8 trackGroups" DrumTrackGroup
    MagneticDrum --> "commutedGroup" DrumTrackGroup

    class DrumTrack {
      id
      DrumTrack(id, group)
    }

    DrumTrack "16 tracks" -* "trackGroup" DrumTrackGroup

    class DrumBlock {
      id
      DrumBlock(id, track)
    }

    DrumBlock "8 blocks" -* "track" DrumTrack
    Octad "2 octads" <--* DrumBlock


    class GeneralSerie {
        getInstruction(line)
        getInstructions()
    }

    class IOSerie {
        instructions
        max_nb_inst = 64
        setInstructions(hexCode)
        getInstruction(line)
        getInstructions()
    }

    class InstructionsArray {

    }

    class Parser {
        parseInstructions(hexCode)
        parseInstruction(TO, AD, OD, OF)
    }
    BullGamma - Parser
    BullGamma "bullGamma" -- "magneticDrum" MagneticDrum

    Serie <|-- IOSerie
    Serie <|-- GeneralSerie
    Octad o---> "8 memories" Memory
    GeneralSerie o---> "16 memories" Memory
    BullGamma *-- "generalMemories 7\ncp, rnl1, rnl2" Memory
    BullGamma -- "mc" CmpMemory
    BullGamma - "selectedOctad" Octad
    IOSerie "ioSerie" -- BullGamma
    GeneralSerie "generalSeries 3" -- BullGamma
    InstructionsArray "instructions" <---* IOSerie

  }

  package WireArray {

      class WireArray {
          editIoSerie()
          generateWires(instructions)
      }


      abstract class ArrayConnection {

      }

      class Constant {
        value
        getValue()
      }

      class InstructionConnection {

      }

      ArrayConnection <|-- Constant
      ArrayConnection <|-- InstructionConnection

      class InstrConnectionTuple {
        value
        getValue()
        setValue()
      }

      class Wire {

      }

      ArrayConnection "ends 2" --o "wire" Wire
      Wire "wires 0..*" <--* WireArray

      InstructionConnection "connections 2" <--* InstrConnectionTuple
      InstrConnectionTuple <-* WireArray

      Constant "constants 16" <--* WireArray
      IOSerie "edit" <--down--o WireArray

  }

  package "Control" {
      class Editor {
          editIoSerie(hexCode)
          editDrum(hexCode)
      }
      IOSerie "edit" <--down--o Editor
      MagneticDrum "edit" <--down--o Editor

      class Execution {
          executeAll()
          executeNextInstruction()
      }
      BullGamma "execution" <--down--o Execution

      class Debug {
          getInstructions(serieId)
          getMemory(id, octad)
          setMemory(value, id, octad)
          getNL()
          setNL(value)
          getMS1()
          setMS1(value)
          getMCMP()
          setMCMP(value)
          getRNL1()
          setRNL1(value)
          getRNL2()
          setRNL2(value)
      }
      BullGamma "debug" <--down--o Debug
  }


  package Assembly {
    abstract class Instruction {
       TO
       AD
       OD
       OF
       executionTime
       Instruction(TO, AD, OD, OF, bullGamma)
       toLineString(): String
      {abstract} execute()
      {abstract} computeExeTime()
    }

    abstract class Operation {
      Operation(TO, AD, OD, OF, bullGamma)
    }

    abstract class OperationWithPreShift {
        OperationWithPreShift(TO, AD, OD, OF, bullGamma)
        execute()
        {abstract} exeInstructionLogic()
    }

    abstract class SmallDivOrMult {
      SmallDivOrMult(TO, AD, OD, OF, bullGamma)
      execute()
      {abstract} compute(mb: Memory)
      {abstract} computeValue()
    }

    abstract class BigDivOrMult {
      BigDivOrMult(TO, AD, OD, OF, bullGamma)
      execute()
      {abstract} compute(mb: Memory)
      {abstract} computeValue()
    }

    Instruction <|-- Operation
    Operation <|-- OperationWithPreShift
    Operation <|-- SmallDivOrMult
    Operation <|-- BigDivOrMult

    InstructionsArray "64 instructions" *-- Instruction

    class V {
      TO = 0
      execute()
      computeExeTime()
    }

    class NOP {
      TO = 0
      AD = 0
      OF % 4 == 0
      execute()
      computeExeTime()
    }

    class VCS {
      TO = 1
      execute()
      computeExeTime()
    }

    class VRS {
      TO = 1
      execute()
      computeExeTime()
    }

    class CD {
      TO = 1
      execute()
      computeExeTime()
    }

    class CO {
      TO = 1
      execute()
      computeExeTime()
    }

    class CSz {
      TO = 1
      execute()
      computeExeTime()
    }

    class CB {
      TO = 1
      execute()
      computeExeTime()
    }

    class ZB {
      TO = 3
      execute()
      computeExeTime()
    }

    class KB {
      TO = 4
      execute()
      computeExeTime()
    }

    class GG {
      TO = 5
      execute()
      computeExeTime()
    }

    class BO {
      TO = 6
      execute()
      computeExeTime()
    }

    class AMD {
      TO = 7
      execute()
      computeExeTime()
    }

    class BD {
      TO = 7
      execute()
      computeExeTime()
    }

    class IL {
      TO = 7
      execute()
      computeExeTime()
    }

    class OB {
      TO = 8
      computeExeTime()
      exeInstructionLogic()
    }

    class CN {
      TO = 9
      computeExeTime()
      exeInstructionLogic()
    }

    class AN {
      TO = 10
      computeExeTime()
      exeInstructionLogic()
    }

    class SN {
      TO = 11
      computeExeTime()
      exeInstructionLogic()
    }

    class MR {
      TO = 12
      computeExeTime()
      exeInstructionLogic()
    }

    class DR {
      TO = 13
      computeExeTime()
      exeInstructionLogic()
    }

    class MC {
      TO = 14
      computeExeTime()
      exeInstructionLogic()
    }

    class DC {
      TO = 15
      computeExeTime()
      exeInstructionLogic()
    }

    V --|> Instruction
    KB --|> Instruction
    BD --|> Instruction
    CB --|> Instruction
    AMD -|> Instruction
    CD -|> Instruction
    Instruction <|- VCS
    Instruction <|- VRS
    Instruction <|-- CO
    Instruction <|-- CSz
    NOP --|> V

    ZB --|> Operation
    IL --|> Operation
    GG -|> Operation
    Operation <|- BO

    OperationWithPreShift <|-- SN 
    OperationWithPreShift <|-- OB
    OperationWithPreShift <|-- CN
    OperationWithPreShift <|-- AN

    SmallDivOrMult <|-- MR
    SmallDivOrMult <|-- DR

    BigDivOrMult <|-- MC
    BigDivOrMult <|-- DC
@endDC
